当将指针传递到C++11中的另一个线程时,会出现竞争条件
When is passing a pointer to another thread in C++11 a race condition?
此代码是否具有竞争条件?
auto x = make_shared<Fun>(1984); //could also be raw ptr
auto t = thread(func, x);
Herb Sutter在C++和Beyond的演讲中也使用了并发队列。
所以如果我有一个队列q
,
auto x = new Fun(1984);
q.push(x);
//other thread
auto ptr = q.pop();
这是比赛条件吗?另一个线程是否可以弹出ptr
,并且仍然可以看到ptr
所指向的内存位置的陈旧值?由于并发队列不在标准中,所以假设我使用的是PPL/TBB队列。
在这两种情况下均为否。
如果不是因为std::thread
的一些特殊性质,第一个例子在原则上是一个确定的竞赛条件。原则上允许编译器对移动进行重新排序,但是构造线程对象具有顺序一致性,这在形式上保证了它的工作。但是,即使它没有这个属性,在实践中创建和启动一个线程也需要相当长的时间(几十万到数百万倍于执行几个移动指令的时间),所以你实际上(不是正式的,而是实际的)可以保证没有种族,即使没有顺序一致性(这种"实际保证"确实有点争议,在悔过的极端情况下可能不成立,但形式保证无论如何都是正确的)。
第二个示例使用并发队列,根据定义,该队列是以不发生竞争条件的方式进行设计的(使用锁或使用无锁算法)1
在任何一种情况下,最终在队列中的指针都保证根本不在那里(在这种情况下,pop
操作将阻塞或失败,其中"失败"意味着使用线程知道此时没有可用的有效指针——它不会假设某个无效值),或者它处于有效状态。将指针添加到队列的原子(锁定或无锁)操作保证了之前发生的对象构造也在之前实现(即队列上没有指针而没有有效对象)
这意味着当从队列中检索对象的指针时,对象也必须是有效的(除非您作弊)。
1这显然假设了队列的正确操作,但这是一个合理的假设。
可能存在竞争条件,但前提是当其他线程开始使用其副本时使用指针x
。
像这样的函数:
void CreateWork(Queue& q){
auto x = new Fun(1984);
// could use x here
q.push(x);
}
因为一旦x
在队列中,调用CreateWork
的线程就不能访问x
。
- 并行块(线程清理器)之外的 OpenMP 中的争用条件;误报?
- 唤醒多个线程以在每个条件下工作一次
- 子线程中的条件变量等待停止主线程中的执行
- 正在连接的等待条件变量的线程会发生什么情况?
- C++11如何在1个线程中使用条件变量处理2个线程安全队列
- 当线程处理不同的类时,应该在哪里声明条件变量、互斥对象
- 如何"stop"正在等待条件变量的分离线程?
- 如何杀死被条件变量锁定的线程?
- 尽管互斥锁,线程中的争用条件
- C++ 多个使用者线程卡在条件变量上
- C++ 多线程中的锁和条件变量问题
- 请解释条件变量在 c++ 线程中的使用,以及为什么我们需要同时使用"unique_lock"和&qu
- C++14 线程/条件变量误解
- 线程功能之一不执行可能的比赛条件
- 条件_variable和unique_lock如何适用于线程安全列表
- 可以在同一条件变量上等待多个线程
- 条件变量,在C++线程中具有 while 循环
- C++线程退出循环条件
- 在C 中处理Boost线程条件
- C++ 多线程:条件变量