如果我写这样的话:
std::atomic<bool> *p = new std::atomic<bool>(false); // At the beginning of the program
//...
void thread1()
{
while (!(*p))
// Do something
}
//...
void thread2()
{
//...
*p = true;
//...
}
thread1
和thread2
将同时运行。 p
的值从未初始化,因此永远不会更改。在这种情况下,取消引用操作是否安全?出于性能原因,我想避免使用原子指针。
答案 0 :(得分:4)
是的,这是安全的。如果没有至少一个线程修改共享变量,则无法进行数据竞争。由于两个线程都没有修改p
,因此没有竞争。
答案 1 :(得分:0)
您发布的代码和问题是两回事。
代码将起作用,因为不取消引用非原子指针。您取消引用std::atomic<bool>*
将导致(运算符重载)顺序一致的提取/存储。这可能不是必要的效率(大多数时候这样的标志用于释放操作),但它是安全的。
否则,只要没有其他线程修改数据,解除引用任何(包括原子变量)的有效非原子指针就是安全。
取消引用非原子指针与写入它的另一个线程仍然是“安全的”,因为它不会崩溃。然而,没有正式保证记忆不会出现乱码(对于对齐的POD,由于处理器如何访问内存而有一个非常实际的保证),但更重要的是,它是不安全的,因为没有内存订购保证。当使用这样的标志时,通常会做这样的事情:
do_work(&buf); // writes data to buf
done = true; // synchronize
这适用于一个线程,但不保证在并发时正常工作。为此,您需要事先保证。否则,在实现对数据的写入之前,另一个线程可能会获取对该标志的更新。
答案 2 :(得分:0)
解除引用(即:读取地址)是intel架构上的原子 。此外,由于不变,我猜它不仅在Intel / AMD上是正确的。但请查看this post以获取更多信息。
澄清:在其他体系结构中,当写入地址时,当只有部分地址被修改时,可以切换线程,因此另一个线程读取的地址将无效。
对于英特尔,如果地址在内存中对齐,则不会发生。
此外,由于*p
是std::atomic<bool>
,因此它已经实现了所需的全部内容(本机,asm,内存防护)。