是否有必要使用std :: atomic来表示线程已完成执行? [英] Is it necessary to use a std::atomic to signal that a thread has finished execution?

查看:137
本文介绍了是否有必要使用std :: atomic来表示线程已完成执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想检查 std :: thread 是否已完成执行。搜索stackoverflow我发现了以下问题,它解决了这个问题问题。接受的答案建议让工作线程在退出之前设置一个变量,并让主线程检查此变量。下面是这种解决方案的最小工作示例:

I would like to check if a std::thread has finished execution. Searching stackoverflow I found the following question which addresses this issue. The accepted answer proposes having the worker thread set a variable right before exiting and having the main thread check this variable. Here is a minimal working example of such a solution:

#include <unistd.h>
#include <thread>

void work( bool* signal_finished ) {
  sleep( 5 );
  *signal_finished = true;
}

int main()
{
  bool thread_finished = false;
  std::thread worker(work, &thread_finished);

  while ( !thread_finished ) {
    // do some own work until the thread has finished ...
  }

  worker.join();
}

有人对已接受的回答发表评论,声称不能使用简单的 bool 变量作为信号,代码被破坏没有内存屏障,并使用 std :: atomic< bool> 。我的初始猜测是,这是错误的,一个简单的 bool 是足够了,但我想确保我没有失去的东西。 上述代码需要 std :: atomic< bool> 才能正确吗?

Someone who commented on the accepted answer claims that one cannot use a simple bool variable as a signal, the code was broken without a memory barrier and using std::atomic<bool> would be correct. My initial guess is that this is wrong and a simple bool is sufficient, but I want to make sure I'm not missing something. Does the above code need a std::atomic<bool> in order to be correct?

让我们假设主线程和worker在不同的socket中运行在不同的CPU上。我认为会发生的是,主线程从它的CPU的缓存读取 thread_finished 。当工作者更新它时,高速缓存一致性协议负责将工作者改变为全局存储器,并使主线程的CPU高速缓存无效,因此它必须从全局存储器读取更新的值。是不是缓存一致性的整个点使像上面的代码只是工作?

Let's assume the main thread and the worker are running on different CPUs in different sockets. What I think would happen is, that the main thread reads thread_finished from its CPU's cache. When the worker updates it, the cache coherency protocol takes care of writing the workers change to global memory and invalidating the main thread's CPU's cache so it has to read the updated value from global memory. Isn't the whole point of cache coherence to make code like the above just work?

推荐答案


有人评论了接受的答案声称,不能使用一个简单的bool变量作为信号,代码被打破没有内存屏障和使用std ::原子是正确的。

Someone who commented on the accepted answer claims that one cannot use a simple bool variable as a signal, the code was broken without a memory barrier and using std::atomic would be correct.

注释器是正确的:一个简单的 bool 是不够的,因为非原子写从线程设置 thread_finished c>到 true 可以重新排序。

The commenter is right: a simple bool is insufficient, because non-atomic writes from the thread that sets thread_finished to true can be re-ordered.

一个静态变量 x 到一些非常重要的数字,然后发出其退出信号,如下所示:

Consider a thread that sets a static variable x to some very important number, and then signals its exit, like this:

x = 42;
thread_finished = true;

当你的主线程看到 thread_finished true ,它假定工作线程已经完成。但是,当你的主线程检查 x 时,它可能会发现它设置了错误的数字,因为上面的两个写已重新排序。

When your main thread sees thread_finished set to true, it assumes that the worker thread has finished. However, when your main thread examines x, it may find it set to a wrong number, because the two writes above have been re-ordered.

当然这只是一个简单的例子来说明一般的问题。使用 std :: atomic 为您的 thread_finished 变量添加一个内存屏障所有写入完成之前。

Of course this is only a simplified example to illustrate the general problem. Using std::atomic for your thread_finished variable adds a memory barrier, making sure that all writes before it are done. This fixes the potential problem of out-of-order writes.

另一个问题是,对非易失性变量的读取可以优化出来 ,所以主线程永远不会注意到 thread_finished 标志的变化。



重要说明:使 thread_finished 强>去解决这个问题;事实上,volatile不应该与线程结合使用 - 它用于处理内存映射硬件。

Another issue is that reads to non-volatile variables can be optimized out, so the main thread would never notice the change in the thread_finished flag.


Important note: making your thread_finished volatile is not going to fix the problem; in fact, volatile should not be used in conjunction with threading - it is intended for working with memory-mapped hardware.

这篇关于是否有必要使用std :: atomic来表示线程已完成执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆