这段代码有竞争条件吗?
auto x = make_shared<Fun>(1984); //could also be raw ptr
auto t = thread(func, x);
Herb Sutter 在 C++ and 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这显然假设队列操作正确,但这是一个合理的假设。
关于c++ - 在 C++11 中,什么时候将指针传递给另一个线程会出现竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18428391/