是否安全地解除引用不同线程中原子对象的READ ONLY非原子指针?

时间:2014-02-01 07:24:47

标签: c++ multithreading pointers atomic

如果我写这样的话:

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;  
    //...
}  

thread1thread2将同时运行。 p的值从未初始化,因此永远不会更改。在这种情况下,取消引用操作是否安全?出于性能原因,我想避免使用原子指针。

3 个答案:

答案 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以获取更多信息。

澄清:在其他体系结构中,当写入地址时,当只有部分地址被修改时,可以切换线程,因此另一个线程读取的地址将无效。

对于英特尔,如果地址在内存中对齐,则不会发生

此外,由于*pstd::atomic<bool>,因此它已经实现了所需的全部内容(本机,asm,内存防护)。