C++ 我是否需要同步C++;

C++ 我是否需要同步C++;,c++,synchronization,primitive,concurrent-programming,C++,Synchronization,Primitive,Concurrent Programming,我的类中有一个volatile bool“play”标志,它由一个线程设置,由另一个线程读取 我需要将调用同步到该标志吗?例如,在此函数中: void stop() { play = false; } 在windows中,他们有_InterlocatedExchange,OSX有OSAtomicAdd64Barrier,我见过这些函数与共享原语一起使用,我需要它们吗 谢谢是的,volatile在任何方面都不意味着线程安全或原子。如果可以,请使用std::mutex和std::uniqu

我的类中有一个volatile bool“play”标志,它由一个线程设置,由另一个线程读取

我需要将调用同步到该标志吗?例如,在此函数中:

void stop() 
{
   play = false;
}
在windows中,他们有_InterlocatedExchange,OSX有OSAtomicAdd64Barrier,我见过这些函数与共享原语一起使用,我需要它们吗


谢谢

是的,
volatile
在任何方面都不意味着线程安全或原子。如果可以,请使用
std::mutex
std::unique\u lock
等,而不是平台说明
std::atomic
是一个很好的选择,在这种情况下可能是最好的选择。

取决于:

如果您使用的CPU具有总存储顺序内存模型(例如x86/x64)或任何只有1个CPU内核的机器,那么您的问题的答案是否定的,因为您声明只有1个线程写入标志,并且在x86上可能会优化屏障指令。如果您在具有宽松内存模型的CPU上编译相同的代码,那么情况会发生变化,然后您可能会发现在x86上完美工作的代码会出现一些奇怪的、难以重现的错误,例如,如果您在ARM或PPC上编译并运行它


volatile
指令防止写入被缓存到某个地方,这可能意味着读取线程看到写入的速度要比
volatile
指令中没有写入的速度快得多。是否要使用它取决于此间隔的重要性,它取决于线程之间是否共享任何其他数据。线程的问题是,一个线程可能会看到来自不同线程的写入,其顺序与最初写入的线程不同。在这种情况下,您需要使用某种_Interlocked*/原子函数或锁(在两个线程中),它们保证在标志对另一个线程可见之前所做的所有更改

如果没有其他共享数据(或者只有只读共享数据),或者您正在x86上运行,那么只使用
volatile
也应该可以。然而,从某种意义上讲,它的工作只是偶然的,没有任何标准的保证,因此,如果您的平台支持它,建议您仍然使用某种形式的原子/互锁/等。将来(即,一旦有了良好的编译器支持),您应该使用C++11的
std::Atomic
,因为这将在平台之间进行移植


您不应该使用纯非易失性变量,如果这样做,编译器可能会决定优化检查<正如camelcc建议的那样,code>volatile与缓存关系不大

某些线程也读取变量吗?是的,它正在被工作线程读取。你确定吗?是否要显示在这种特定情况下数据竞争是如何发生的?除非您在读取值的线程中的循环中检查
play
,否则您将在某个时刻错过更新,除非您以某种方式对其进行同步
volatile
在其含义上几乎与原子性正交。请参阅此处以获得另一个答案:我了解volatile是什么,但假设主线程没有读取
play
,并且工作线程没有编写
play
(这是我从问题中了解到的)-我看不到竞态条件是如何发生的(尽管我无法找到证明它不会发生的方法)。你说它仍然不安全->可能会发生数据竞争,我正在寻找能证明你答案正确的致命案例。如果你不想确切知道标志何时更新,那么你就不必使用原子/同步。但是,除了在某个点上会看到更新值外,标准不保证其他线程何时会看到更新值。在这里,这可能没那么重要。这实际上取决于您的读卡器线程正在做什么。@amit:
[intro.multithread]/4
:“如果其中一个修改内存位置(1.7),而另一个访问或修改同一内存位置,则两个表达式求值会冲突。”以及
[intro.multithread]/21
:如果一个程序的执行在两个线程中包含两个冲突的操作,则该程序的执行包含一个数据竞争,其中至少一个不是原子的,并且两个操作都不在另一个之前发生。任何这样的数据竞争都会导致未定义的行为。“。如果只有一个线程在写,他不需要原子变量,如果性能很重要,可能有很好的理由不使用原子变量。如果您想跨非x86 CPU进行移植,可能需要在写入线程中设置内存屏障,而且volatile保证在Microsoft编译器(不考虑CPU)上实现这一点,尽管不是gcc。