在 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。可能是真的,可能是假的,也可能是鼻魔。
我有一个代码在工作,它启动多个线程来执行一些操作,如果其中任何一个失败,它们将共享变量设置为 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() 是一个完整的内存屏障 (
在这种情况下是否需要我发布的修复程序(在注释代码中)(或者如果这个错误可能是另一个修复程序)?
是否有可能读取 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。可能是真的,可能是假的,也可能是鼻魔。