簡體   English   中英

Volatile 上的原子變量

[英]Atomic variables over Volatile

由於原子變量是易變的,即使您只需要易變性方面,始終使用原子變量是否有任何缺點?

變量不能是原子的。 原子性和易失性之間有明顯的區別。

原子性:如果在給定時間只有一個線程可以執行一組指令,則該操作稱為原子性。

易變:易變的性質確保了可見性。 如果一個線程修改了一些易失性狀態,其他線程將獲得最近更新的狀態。

例子 :

volatile boolean flag; 


public void flipTheFlag(){
  if(flag == true){
      flag = false;
  }else{
      flag = true;
  }
}

如果多個線程正在執行flipTheFlag 操作,即使flag 是volatile 變量,flag 的值也會不確定。 這就是為什么操作 flipTheFlag 需要是原子的。 我們可以通過添加關鍵字“同步”來使 flipTheFlag 操作原子化。

  1. 當創建最終的Atomic對象后,不同的線程使用該對象來更改內部狀態時,一切都像volatile 一樣

    然而,周圍有一個額外的對象實例。 消耗內存和速度性能。 在這種情況下,它應該是常量/有效最終的,並且它的創建應該其他線程可以訪問之前完成。

  2. 另一個方面 - 我實際上不記得從 java 參考中讀取的正確性,但在其他地方讀過 - 是有幾個字段,當一個字段在修改時volatile時,其他字段也將針對其他線程更新。

  3. 原子常量(或類似的 1 項常量數組)仍然具有可變狀態,有時會被濫用以使用只能訪問常量的Stream操作來收集聚合結果。 這意味着Atomic並不意味着多線程使用。

  4. x = x + c; ( volatile x ) 您將讀取最新的x ,但是在添加c ,另一個線程可能會更改x並且您仍然會為 x 分配一個陳舊的總和。 這里需要原子性。 或者if (x > 0) x = c; .

所以要回答這個問題:根據脆弱的上下文,它們在某種程度上是可以互換的。 我可以理解您為什么更喜歡 Atomic,但在一些簡單的情況下, volatile性能要高得多,尤其是在細粒度並發中。

最后一句話:我不是完全有信心,我在這里是否完全正確。

從並發的角度來看,以下之間沒有區別:

final AtomicInteger foo1 = new AtomicInteger();

volatile int foo2;

foo1.get/set 與 foo2 的讀取和寫入相同。 兩者都將提供原子性、可見性和排序保證。 如果您查看例如 AtomicInteger 的代碼,您將看到一個 volatile int 變量。

Atomic 的主要用例是很容易進行讀修改寫操作,例如增加計數器。 並且您可以訪問更輕松的排序形式,例如 getRelease 和 setAcquire。 但是你可以使用 AtomicFieldReference 和 VarHandles 做同樣的事情(雖然語法不太漂亮)。

atomic 的一個缺點是額外的內存使用和間接性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM