3

我的班级中有一个 volatile bool 'play' 标志,该标志由一个线程设置并由另一个线程读取。

我是否需要将调用同步到该标志?例如在这个函数中:

void stop() 
{
   play = false;
}

在 Windows 中他们有 _InterlockedExchange 而 OSX 有 OSAtomicAdd64Barrier,我已经看到这些函数与共享原语一起使用,我需要它们吗?

谢谢

4

3 回答 3

3

是的,并且volatile绝不意味着线程安全或原子。如果可以,请使用std::mutex等,而不是平台细节。是不错的选择——在这种情况下可能是最好的。std::unique_lockstd::atomic

于 2012-12-26T08:10:45.860 回答
1

依靠:

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

volatile指令防止写入被缓存在某处,并且可能意味着读取线程比volatile指令不存在时更快地看到写入。是否要使用这个取决于这个间隔有多重要

于 2012-12-26T13:33:31.193 回答
1

这取决于线程之间是否有任何其他数据共享。线程的问题是,一个线程可能会以与最初创建它们的线程不同的顺序看到来自不同线程的写入。在这种情况下,您需要使用某种 _Interlocked*/Atomic 函数或锁(在两个线程中),他们保证在标志之前所做的所有更改对另一个线程可见。

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

您不应该使用裸非易失性变量,如果这样做,编译器可能会决定优化检查。volatile正如 camelccc 所暗示的那样,与缓存几乎没有关系。

于 2013-02-06T15:35:46.717 回答