2014-11-06 174 views
4

我的问题涉及到的std ::原子和数据,这个指针指向。如果在线程1我有原子指针C++和在线程之间传递对象

Object A; 
std:atomic<Object*> ptr; 
int bar = 2; 
A.foo = 4; //foo is an int; 
ptr.store(*A); 

,并且如果在螺纹2我观察到ptr指向A,可以我被保证ptr-> foo是4和杆是2?原子指针的缺省内存模型(顺序一致)是否确保在原子存储之前发生的非原子分配(在本例中为A.foo)在其他线程看到相同的atomic.store对于这两种情况?

如果有帮助或有事项,我使用的x64(我只关心这个平台),GCC(与支持原子能版本)。

+1

我想你的意思'ptr.store(A)'? 'ptr.store(* A)'没有任何意义(除非'Object'定义了Object * Object :: operator *();'...)。 – cdhowie 2014-11-06 18:50:35

+1

相关:[C++ 11引入了标准化的内存模型。这是什么意思?它是如何影响C++编程的?](http://stackoverflow.com/questions/6319146/c11-introduced-a-standardized-memory-model-what-does-it-mean-and-how-is- it-g) – Casey 2014-11-06 19:58:01

回答

4

在默认情况下,C++ - 11原子操作具有获取/释放语义。

让看到的你的店线程也会看到之前执行的所有操作。

你可以找到一些更细节here

+5

+1。 (实际上,默认值是'std :: memory_order_seq_cst',它具有比获取/释放更强的保证,但实际上这就是这里所需要的。) – Cameron 2014-11-06 19:53:38

10

答案是肯定的,也许没有

存储模式的原则:

C++ 11原子能使用by defaultstd::memory_order_seq_cst内存排序,这意味着操作顺序一致

的这种语义的所有操作的是排序的,就好像所有这些操作进行顺序:

  • C++标准节29.3/3说明了这是如何工作的原子能:“必有顺序和修改订单所有受影响的位置,是对所有memory_order_seq_cst操作的单个总订单S,与一致“之前发生”,使得加载一个值的每个memory_order_seq_cst 操作根据任一前述最后修改观察到这个顺序S,或者是不是memory_order_seq_cst的操作的结果。

  • 的部分1.10/5解释如何影响也非原子公司:” 库定义了许多专门被确定为同步操作的原子操作(...)的。这些操作在使一个线程中的分配对另一个线程可见时起到特殊作用。

的回答你的问题是肯定的!

风险与非原子数据

然而,你应该知道,现实中的一致性保证是对非较为有限 - 原子值。

假设一个第一执行方案:

(thread 1) A.foo = 10; 
(thread 1) A.foo = 4;  //stores an int 
(thread 1) ptr.store(&A); //ptr is set AND synchronisation 
(thread 2) int i = *ptr; //ptr value is safely accessed (still &A) AND synchronisation 

这里,i是4。因为ptr是原子的,螺纹(2)安全地得到值&A当它读取指针。内存排序可确保其他线程看到在ptr之前进行的所有分配(“发生之前”约束)。

但是,假设第二执行情况:

(thread 1) A.foo = 4;  //stores an int 
(thread 1) ptr.store(&A); //ptr is set AND synchronisation 
(thread 1) A.foo = 8;  // stores int but NO SYNCHRONISATION !! 
(thread 2) int i = *ptr; //ptr value is safely accessed (still &A) AND synchronisation 

这里的结果是不确定的。它可能是4,因为内存顺序保证在其他线程看到ptr分配之前发生了什么。但是没有什么能阻止事后做出的任务。所以它可能是8

,如果您曾经有过*ptr = 8;代替A.foo=8;,那么你将不得不再次肯定:i将是8。

你可以用这个实验来验证这个例如:

void f1() { // to be launched in a thread 
    secret = 50; 
    ptr = &secret; 
    secret = 777; 
    this_thread::yield(); 
} 
void f2() { // to be launched in a second thread 
    this_thread::sleep_for(chrono::seconds(2)); 
    int i = *ptr; 
    cout << "Value is " << i << endl; 
} 

结论

最后,在回答你的问题是肯定的,但前提是没有其他变化到非原子数据HAP同步后的笔。主要风险是只有ptr是原子。但是这并不适用于指向的值。

要注意的是,当您将原子指针重新分配给非原子指针时,尤其是指针会带来进一步的同步风险。

例子:

// Thread (1): 
std:atomic<Object*> ptr; 
A.foo = 4; //foo is an int; 
ptr.store(*A); 

// Thread (2): 
Object *x; 
x=ptr;  // ptr is atomic but x not ! 
terrible_function(ptr); // ptr is atomic, but the pointer argument for the function is not !