我有一个代码正在启动多个执行某些操作的线程,如果其中任何一个失败,他们会将共享变量设置为 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 变量。
答案 0 :(得分:2)
上面的代码表示数据竞争,使用join
无法改变这一事实。如果只有一个线程写入变量,那就没问题了。但是你有两个线程写入它,它们之间的没有同步。那是一场数据竞赛。
atomic_bool
只是意味着&#34;该线程操作的所有副作用已经完成,现在对您可见。&#34;这不会在该线程与任何线程其他之间创建排序或同步,而不是您自己的。
如果您使用了convertAndSendToUser
,则它不会是UB;它将被保证是错误的。但是因为有数据竞争,你会得到纯粹的UB。它可能是真实的,虚假的或鼻腔的恶魔。