这两个操作如果是互斥操作,一定要序列化吗?

问题描述 投票:0回答:1

考虑这个例子:

#include <iostream>
#include <atomic>

void close(int);
void use(int);
int create();

int main(){
  std::atomic<bool> is_shutdown = false;
  int fd = create();
  std::thread t1([&](){
    is_shutdown.store(true);
    close(fd);  // #1
  });
  std::thread t2([&]{
     if(is_shutdown.load()){  // #2
         return;
     }
     use(fd);  // #3
  });
  t1.join();
  t2.join();
}

假设

use(fd)
fd
close
关闭后会出现异常。在
#2
false
关闭后,
fd
可能仍然读取
#1
。所以,快速检查并不可靠。是不是意味着这两个操作必须串行化?换句话说,它们必须被放置在关键部分,以便它们被专门执行。

c++ multithreading atomic
1个回答
0
投票

是的。您需要序列化这些操作。即使您使用 std::atomic 进行 is_shutdown,仍然存在竞争条件。

这就是可能发生的事情:

线程 t2 检查 is_shutdown 并发现它是 false (#2)。

在 t2 调用 use(fd) 之前,线程 t1 将 is_shutdown 设置为 true 并关闭 fd (#1)。

现在 t2 在关闭的 fd 上调用 use(fd) (#3)。

这意味着 t2 关闭后可能会使用 fd,这可能会导致错误。检查 (is_shutdown.load()) 和操作 (use(fd)) 不会同时发生。

您应该使用互斥体或某种同步来确保当一个线程使用 fd 时,另一个线程不会关闭它。这样,要么线程看到关闭已经发生并且不使用 fd,要么它安全地使用 fd 而不必担心它被关闭。

© www.soinside.com 2019 - 2024. All rights reserved.