在thread :: join上是否存在一个带有synchronized-with关系的隐式内存屏障?

时间:2017-02-11 11:16:06

标签: c++ multithreading c++11 memory-barriers memory-fences

我有一个代码正在启动多个执行某些操作的线程,如果其中任何一个失败,他们会将共享变量设置为 false

然后主线程加入所有工作线程。模拟看起来大致如此(我评论了可能的解决方案,我不知道是否需要):

#include <thread>
#include <atomic>
#include <vector>
#include <iostream>
#include <cassert>

using namespace std;

//atomic_bool success = true;
bool success = true;

int main()
{
    vector<thread> v;
    for (int i = 0; i < 10; ++i)
    {
        v.emplace_back([=]
        {
            if (i == 5 || i == 6)
            {
                //success.store(false, memory_order_release);
                success = false;
            }
        });
    }
    for (auto& t : v)
        t.join();

    //assert(success.load(memory_order_acquire) == false);
    assert(success == false);

    cout << "Finished" << endl;
    cin.get();
    return 0;
}

主线程是否有可能将成功变量读为 true ,即使其中一个工作人员将其设置为 false

我发现 thread :: join()是一个完整的内存屏障(source),但这意味着的关系与以下读取有关来自主线程的成功变量,以便我们保证获得最新值?

我在这种情况下发布的修正(在评论代码中)是否是必要的(或者如果这个错误可能是另一个修复)?

成功变量的读取是否有可能被优化掉(因为它不易变)并且无论是否存在隐式内存屏障,我们都将获得旧值在 thread :: join

代码被假定在多个架构上工作(不记得所有这些,我没有在我面前的makefile)但是至少有x86,amd64,itanium,arm7。 < / p>

感谢您提供任何帮助。

编辑:我修改了这个例子,因为在实际情况中,一个线程可以尝试写入 success 变量。

1 个答案:

答案 0 :(得分:2)

上面的代码表示数据竞争,使用join无法改变这一事实。如果只有一个线程写入变量,那就没问题了。但是你有两个线程写入它,它们之间的没有同步。那是一场数据竞赛。

atomic_bool只是意味着&#34;该线程操作的所有副作用已经完成,现在对您可见。&#34;这不会在该线程与任何线程其他之间创建排序或同步,而不是您自己的。

如果您使用了convertAndSendToUser,则它不会是UB;它将被保证是错误的。但是因为有数据竞争,你会得到纯粹的UB。它可能是真实的,虚假的或鼻腔的恶魔。