c++ - 在 C++11 中,什么时候将指针传递给另一个线程会出现竞争条件?

标签 c++ c++11 race-condition

这段代码有竞争条件吗?

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/

相关文章:

C++ ffmpeg "Starting new cluster"错误

c++ - 如何在类 debian 系统中使用 libapt(或 libept)来列出包并获取它们的信息?

javascript - DOM 操作未立即执行

c# - 仅使用 async/await 时是否存在竞争条件?

c++ - Q_DECLARE_INTERFACE() 和 Q_PLUGIN_METADATA(),interface id string 需要匹配吗?

python - 如何避免与 makedirs 的竞争条件?

java - 使用 JNA 通过 Java 恢复对 Windows 目录的继承

c++ - 避免双重包含 : Preprocessor directive vs. makefile

c++ - 重载加号运算符的正确方法是什么?

c++ - 如果父线程/主线程死亡,std::async 调用会发生什么