如果我像 -
一样声明并定义一个原子指针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;
还有其他方法可以原子地做同样的事情吗? 我的理解是否有缺陷?
答案 0 :(得分:6)
df = sql_c.read.csv('data.csv')
涉及分配内存,
是
构建
new T()
对象
是
然后它将自动分配给iptr。
完全(几乎,它是这里使用的对象的地址)。它用于在内存分配和构造完成后初始化原子。
T
可以简单地构造,在这种情况下,构造T
不应该抛出但是一些用户定义的T
可能抛出。
如果确实如此,则不会达到原子的初始化。如果c'tor抛出,T
表达式不会泄漏内存,它会调用正确的deallcoation函数。所以你的临时和直接使用新表达式具有完全相同的语义。
答案 1 :(得分:2)
新的未命名对象的创建不是原子的,但它不需要。 [如上所述,任何异常只会影响在分配给原子之前创建的临时对象的生命周期,并且应该清理得很好。]
指向原子指针的临时指针是原子的。
我最关心的是,因为它代表你的代码无法检测另一个线程是否完成了赋值,所以你必须考虑使用testandset或swap。然后你有麻烦,测试/交换失败,你有一个临时指针指向你不再需要的对象。
如果您使用局部变量(而不是未命名的临时变量),您将有机会清理它。
如果你对原子使用智能指针,那么它会自毁。
但是,在许多情况下,如果不创建临时对象,除非确实需要它,否则更好,但这意味着在整个创建过程中使用互斥锁,但在进入互斥锁之前可以进行轻量级检查。这更像是单身静态变量所做的事情 如果你正在创建一个单例,那么没有真正的缺点,因为其他线程无论如何都必须等待。