初始化原子指针原子?如果初始化或内存分配抛出会发生什么?

时间:2018-05-14 09:57:56

标签: c++ c++11 c++14

如果我像 -

一样声明并定义一个原子指针
std::atomic<int*> iptr = new int(1);    
std::atomic<T*> iptr = new T();

据我所知,整个操作不是原子的。

new T()涉及分配内存,构造T对象,然后将其原子分配给iptr。 T可以是简单的可构造的,在这种情况下,构造T不应该抛出但是一些用户定义的T可以抛出。

如果在T构造或内存分配之间,某些其他线程使用iptr?

这个操作真的是原子的吗?使其成为原子的一种方法是打破声明和定义,例如。

T* temp = new T();
std::atomic<T*> iptr = temp;    

还有其他方法可以原子地做同样的事情吗? 我的理解是否有缺陷?

2 个答案:

答案 0 :(得分:6)

  

df = sql_c.read.csv('data.csv') 涉及分配内存,

  

构建new T()对象

  

然后它将自动分配给iptr。

完全(几乎,它是这里使用的对象的地址)。它用于在内存分配和构造完成后初始化原子

  

T可以简单地构造,在这种情况下,构造T不应该抛出但是一些用户定义的T可能抛出。

如果确实如此,则不会达到原子的初始化。如果c'tor抛出,T表达式不会泄漏内存,它会调用正确的deallcoation函数。所以你的临时和直接使用新表达式具有完全相同的语义。

答案 1 :(得分:2)

新的未命名对象的创建不是原子的,但它不需要。 [如上所述,任何异常只会影响在分配给原子之前创建的临时对象的生命周期,并且应该清理得很好。]

指向原子指针的临时指针是原子的。

我最关心的是,因为它代表你的代码无法检测另一个线程是否完成了赋值,所以你必须考虑使用testandset或swap。然后你有麻烦,测试/交换失败,你有一个临时指针指向你不再需要的对象。

如果您使用局部变量(而不是未命名的临时变量),您将有机会清理它。

如果你对原子使用智能指针,那么它会自毁。

但是,在许多情况下,如果不创建临时对象,除非确实需要它,否则更好,但这意味着在整个创建过程中使用互斥锁,但在进入互斥锁之前可以进行轻量级检查。这更像是单身静态变量所做的事情 如果你正在创建一个单例,那么没有真正的缺点,因为其他线程无论如何都必须等待。