spo*_*ang 22 c++ multithreading volatile
假设有运行两个线程Thread1(),并Thread2()分别.线程1只设置一个全局标志来告诉线程2退出,线程2定期检查它是否应该退出.
volatile bool is_terminate = false;
void Thread1()
{
is_terminate = true;
}
void Thread2()
{
while (!is_terminate) {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我想问上面的代码是否安全,假设访问is_terminate是原子的.我已经知道许多材料状态,volatile一般不能确保线程安全.但是在只共享一个原子变量的情况下,我们真的需要使用锁来保护共享变量吗?
jal*_*alf 17
它可能有点线程安全.
线程安全往往取决于上下文.如果你从未读过它,更新bool 总是线程安全的.如果您确实从中读取,那么答案取决于您何时从中读取,以及读取的含义.
在某些CPU上,但不是全部,对类型对象的写入bool将是原子的.x86 CPU通常会使其成为原子,但其他人可能不会.如果更新不是原子的,那么添加volatile对您没有帮助.
但下一个问题是重新排序.编译器(和CPU)将按volatile指定的顺序执行对变量的读/写操作,而不进行任何重新排序.这很好.
但它无法保证volatile相对于所有非内存访问重新排序一个内存访问volatile.所以一个常见的例子是你定义某种标志来保护对资源的访问,你创建标志volatile,然后编译器移动资源访问,以便在检查标志之前发生.允许这样做,因为它没有重新排序两个volatile访问的内部排序,而只是一个volatile和一个非访问volatile.
老实说,我问的问题是为什么不正确呢?有可能volatile在这种情况下工作,但为什么不为自己省去麻烦,并使它更清楚,它是正确的?相反,在它周围拍打一个记忆障碍.
Bo *_*son 11
它不是线程安全的.
例如,如果线程在具有单独高速缓存的CPU上运行,则没有语言规则表明在编写volatile变量时要同步高速缓存.如果有的话,另一个线程可能在很长一段时间内都看不到变化.
以另一种方式回答:
如果volatile足够线程安全,为什么C++ 0x用原子操作添加整章?
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2047.html