2017-10-09 107 views
1

Multiple assignment in one line後,我很想知道這對原子數據類型是如何工作的,特別是對於布爾類型的例子。在原子布爾變量的一個語句中多次賦值

考慮:

class foo { 
    std::atomic<bool> a; 
    std::atomic<bool> b; 
    public: 
    void reset(); 
    [...] //Other methods that might change a and b 
} 

是否有任何區別:

void foo::reset() { 
    a = false; 
    b = false; 
} 

和:

void foo::reset() { 
    a = b = false; 
} 

也就是說,在第二種情況下,可以在發生b分配後false,另一個線程集btrue在讀取b之前將其值分配給a,以便在指令結束時a的值爲true

(這也意味着後者的版本似乎是低效率)

+2

硬盤沒有看到實際的編譯器輸出的說舊值,但'的std ::原子::運算符=()'應該返回傳遞給它的價值,所以我認爲'a = ...'根本不會讀取'b'的值,它只會從'operator ='的輸出中接收'false'。現在,在多線程情況下,當'reset()'退出時,'b'仍然可以是'true',但那是另一回事。 –

+0

@RemyLebeau好吧,那麼我的問題幾乎可以回答,不應該有任何區別,否則編譯器會是次優的。謝謝! (當然,在'reset'結束時,如果另一個線程干預,'b'可能是'true') – Antonio

回答

3

是的,有

a = false; 
b = false; 

a = b = false; 

如果ab是原子之間的差。由於分配從右到左進行,後者相當於

b = false; 
a = false; // since atomic::operator= (from above) returns its argument 

從第一個版本不同,因爲ab是原子和assignment is done彷彿std::atomic::store被稱爲與存儲順序memory_order_seq_cst。從而,存儲器模型guarantees

a single total modification order of all atomic operations that are so tagged. 

其結果是,第二線程在反向順序存儲(a = b = false;的可觀察的以下三種方式一個的變化執行原子負載(bool a_observed = a.load(); bool b_observed = b.load();) :兩個b

  • 舊值a
    • 負載a,負載bba
  • b和舊值
  • 新價值a
    • b,負載aa,負載b
    • 店面b,加載a,負載b商店a
    • 負載a,存儲b商店a,負載b
    • 負載a,存儲b,負載b商店a
  • 爲新值ba
    • 商店b,存儲a,負載a,負載b

相反,memory_order_seq_cst爲前b保證前a同時存儲b(在其他線程)裝載a以下從未觀察到

    a
  • 新的價值和b
+0

謝謝,我已經測試過[這裏](https:// godbolt .org/g/kozyTp)爲Clang 3.8 – Antonio

1

Godbolt link

有兩者之間的差異很小。唯一真正的區別是分配順序被翻轉。如果打開優化,則無法區分。

+0

非常酷的鏈接和網站!實際上,當使用更復雜的定義時,差別在於即使在優化時順序也會保留https://godbolt.org/g/kozyTp – Antonio