在 thread::join 上是否存在具有同步关系的隐式内存屏障?

Is there an implicit memory barrier with synchronized-with relationship on thread::join?

我有一个代码在工作,它启动多个线程来执行一些操作,如果其中任何一个失败,它们将共享变量设置为 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() 是一个完整的内存屏障 () 但这是否意味着 synchronized-with 与以下从主线程读取 success 变量的关系,以便我们保证获得最新值?

在这种情况下是否需要我发布的修复程序(在注释代码中)(或者如果这个错误可能是另一个修复程序)?

是否有可能读取 success 变量将被优化掉(因为它不是易变的)并且我们将获得旧值,而不管 应该存在 thread::join?

上的隐式内存屏障

该代码应该适用于多种架构(不记得所有架构,我面前没有 makefile)但至少有 x86、amd64、itanium、arm7。

感谢您对此的任何帮助。

编辑:我已经修改了示例,因为在实际情况下,不止一个线程可以尝试写入 success 变量。

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

join 只是意味着 "all side effects of that thread's operation have completed and are now visible to you." 不会在该线程与任何线程 other 之间创建排序或同步。

如果你用的是atomic_bool,那就不是UB;它将保证是错误的。但是因为存在数据竞争,你得到的是纯粹的 UB。可能是真的,可能是假的,也可能是鼻魔。