从线程调用原子数据成员
Posted
技术标签:
【中文标题】从线程调用原子数据成员【英文标题】:Atomic data member calling from a thread 【发布时间】:2016-12-22 00:08:17 【问题描述】:有人可以帮我理解我在这里做错了什么吗? 当我将类的数据成员设为非原子时,它工作正常。
class AtomicTest
atomic<int> A 0 ;
atomic<int> B 0 ;
public :
AtomicTest()
void func1()
A = 1;
cout << "func1 " << A << endl;;
void func2()
cout << "func2 " << A << endl;
A = A + 1;
cout << A << endl;
;
int main()
AtomicTest a;
thread t1(&AtomicTest::func1, std::ref(a)); // I tried to move as well, i know ref would share data between two threads but i can use mutex to protect data if its needed but i cannot even call the func1
//thread t2(&AtomicTest::func2, std::ref(a));
t1.join();
//t2.join();
return 0;
【问题讨论】:
我想你没试过:std::bind(&AtomicTest::func1, std::ref(a))
作为线程构造函数的唯一参数?
我肯定没有,因为我不知道为什么它会这样工作。我可以知道为什么它不能那样工作,而是使用绑定吗?
有人能告诉我问题是什么吗?使用 clang 对我来说效果很好。
@DietmarKühl 不适合我。我使用的是 clang 3.8(苹果的端口),它在attempt to invoke a deleted constructor 上呕吐。通过std::bind
扭转它或简单地使用&a
作为第二个参数可以消除错误。顺便说一句,节日快乐。
@WhozCraig:clang-3.9 似乎解决了这个问题。当然,是代码确实不编译的问题,例如因为它缺少必要的包含指令。
【参考方案1】:
由于在这种情况下没有额外同步的并发性,无法预测程序行为:
A = A + 1;
这个简单的行包含 1 个原子 load
和 1 个原子 store
操作。即使是默认内存顺序 (std::memory_order_seq_cst
) 也不能为您提供关于这两个线程的混合同时执行的任何保证。标准说这种情况有一个未定义的行为——你的变量存在数据竞争(不管是不是atomic
)。
尝试添加一些锁原语(如std::mutex
)或更改逻辑以使用特殊的原子函数(如fetch_add
、exchange
等)。在cpp-reference 上查看更多信息。
【讨论】:
我知道互斥体,并且我知道数据竞争条件。我所担心的是为什么那个线程调用没有运行。我提到的和评论一样。不过,我不知道 fetch_add 和 exchange。感谢您的信息 对不起,也许我没有理解确切的问题,使代码工作的明显方法是检查include
并使用--std=c++11
指令。顺便说一句(带有必要的包含、指令和库),它可以编译并适用于所有现代编译器(参见这个不错的 tool)。以上是关于从线程调用原子数据成员的主要内容,如果未能解决你的问题,请参考以下文章