一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java多線程編程之Volatile的實現原理

Java多線程編程之Volatile的實現原理

2020-10-09 21:56CBDoctor Java教程

這篇文章為大家講解Java多線程編程之Volatile的實現原理,有需要的朋友可以參考下

Volatile變量

在程序設計中,尤其是在C語言、C++、C#和Java語言中,使用volatile關鍵字聲明的變量或對象通常擁有和優(yōu)化和(或)多線程相關的特殊屬性。通常,volatile關鍵字用來阻止(偽)編譯器對某些其認為無法“被代碼本身”改變的代碼(變量/對象)進行優(yōu)化。如在C語言中,volatile關鍵字可以用來提醒編譯器它后面所定義的變量隨時有可能改變,因此編譯后的程序每次需要存儲或讀取這個變量的時候,都會直接從變量地址中讀取數據。如果沒有volatile關鍵字,則編譯器可能優(yōu)化讀取和存儲,可能暫時使用寄存器中的值,如果這個變量由別的程序更新了的話,將出現不一致的現象。 在C環(huán)境中,volatile關鍵字的真實定義和適用范圍經常被誤解。雖然C++、C#和Java都從C中神秘地“繼承”了volatile,在這些編程語言中volatile的用法和語義卻大相徑庭。【維基百科】

通俗點講解上面這句話,意思就是,編譯器為了快速讀寫,會將數據放到寄存器緩存中,而使用了volatile修飾以后,告訴編譯器,不要對該變量進行優(yōu)化,每次讀取都從內存中去讀取。

鎖提供了兩種主要特性:互斥(mutual exclusion) 和可見性(visibility)。互斥即一次只允許一個線程持有某個特定的鎖,因此可使用該特性實現對共享數據的協調訪問協議,這樣,一次就只有一個線程能夠使用該共享數據??梢娦砸訌碗s一些,它必須確保釋放鎖之前對共享數據做出的更改對于隨后獲得該鎖的另一個線程是可見的 —— 如果沒有同步機制提供的這種可見性保證,線程看到的共享變量可能是修改前的值或不一致的值,這將引發(fā)許多嚴重問題。

Volatile 變量具有 synchronized 的可見性特性,但是不具備原子特性。這就是說線程能夠自動發(fā)現 volatile 變量的最新值。Volatile 變量可用于提供線程安全,但是只能應用于非常有限的一組用例:多個變量之間或者某個變量的當前值與修改后值之間沒有約束。因此,單獨使用 volatile 還不足以實現計數器、互斥鎖或任何具有與多個變量相關的不變式(Invariants)的類

1.1 正確使用 volatile 變量的條件

 

您只能在有限的一些情形下使用 volatile 變量替代鎖。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:

  • 對變量的寫操作不依賴于當前值。
  • 該變量沒有包含在具有其他變量的不變式中。

第一個條件的限制使 volatile 變量不能用作線程安全計數器。雖然增量操作(x++)看上去類似一個單獨操作,實際上它是一個由讀?。薷模瓕懭氩僮餍蛄薪M成的組合操作,必須以原子方式執(zhí)行,而 volatile 不能提供必須的原子特性。實現正確的操作需要使 x 的值在操作期間保持不變,而 volatile 變量無法實現這點。(然而,如果將值調整為只從單個線程寫入,那么可以忽略第一個條件。)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
清單 1. 非線程安全的數值范圍類
@NotThreadSafe
public class NumberRange {
    private int lower, upper;
 
    public int getLower() { return lower; }
    public int getUpper() { return upper; }
 
    public void setLower(int value) {
        if (value > upper)
            throw new IllegalArgumentException(...);
        lower = value;
    }
 
    public void setUpper(int value) {
        if (value < lower)
            throw new IllegalArgumentException(...);
        upper = value;
    }
}

這種方式限制了范圍的狀態(tài)變量,因此將 lower 和 upper 字段定義為 volatile 類型不能夠充分實現類的線程安全;從而仍然需要使用同步。否則,如果湊巧兩個線程在同一時間使用不一致的值執(zhí)行 setLower 和 setUpper 的話,則會使范圍處于不一致的狀態(tài)。例如,如果初始狀態(tài)是(0, 5),同一時間內,線程 A 調用 setLower(4) 并且線程 B 調用 setUpper(3),顯然這兩個操作交叉存入的值是不符合條件的,那么兩個線程都會通過用于保護不變式的檢查,使得最后的范圍值是 (4, 3) —— 一個無效值。至于針對范圍的其他操作,我們需要使 setLower()和 setUpper() 操作原子化 —— 而將字段定義為 volatile 類型是無法實現這一目的的?! ?/p>

1.2  性能考慮

 

很難做出準確、全面的評價,例如 “X 總是比 Y 快”,尤其是對 JVM 內在的操作而言。(例如,某些情況下 VM 也許能夠完全刪除鎖機制,這使得我們難以抽象地比較 volatile 和 synchronized 的開銷。)就是說,在目前大多數的處理器架構上,volatile 讀操作開銷非常低 —— 幾乎和非 volatile 讀操作一樣。而 volatile 寫操作的開銷要比非 volatile 寫操作多很多,因為要保證可見性需要實現內存界定(Memory Fence),即便如此,volatile 的總開銷仍然要比鎖獲取低。

 

很多并發(fā)性專家事實上往往引導用戶遠離 volatile 變量,因為使用它們要比使用鎖更加容易出錯。然而,如果謹慎地遵循一些良好定義的模式,就能夠在很多場合內安全地使用 volatile 變量。要始終牢記使用 volatile 的限制 —— 只有在狀態(tài)真正獨立于程序內其他內容時才能使用 volatile —— 這條規(guī)則能夠避免將這些模式擴展到不安全的用例。

1.3 正確使用 volatile 的模式

 

?
1
2
3
4
5
6
7
8
9
10
11
12
清單 2. 將 volatile 變量作為狀態(tài)標志使用
volatile boolean shutdownRequested;
 
...
 
public void shutdown() { shutdownRequested = true; }
 
public void doWork() {
    while (!shutdownRequested) {
        // do stuff
    }
}

 

很可能會從循環(huán)外部調用 shutdown() 方法 —— 即在另一個線程中 —— 因此,需要執(zhí)行某種同步來確保正確實現 shutdownRequested 變量的可見性。(可能會從 JMX 偵聽程序、GUI 事件線程中的操作偵聽程序、通過 RMI 、通過一個 Web 服務等調用)。然而,使用synchronized 塊編寫循環(huán)要比使用清單 2 所示的 volatile 狀態(tài)標志編寫麻煩很多。由于 volatile 簡化了編碼,并且狀態(tài)標志并不依賴于程序內任何其他狀態(tài),因此此處非常適合使用 volatile。

這種類型的狀態(tài)標記的一個公共特性是:通常只有一種狀態(tài)轉換;shutdownRequested 標志從 false 轉換為 true,然后程序停止。這種模式可以擴展到來回轉換的狀態(tài)標志,但是只有在轉換周期不被察覺的情況下才能擴展(從 false 到 true,再轉換到 false)。此外,還需要某些原子狀態(tài)轉換機制,例如原子變量。

與鎖相比,Volatile 變量是一種非常簡單但同時又非常脆弱的同步機制,它在某些情況下將提供優(yōu)于鎖的性能和伸縮性。如果嚴格遵循 volatile 的使用條件 —— 即變量真正獨立于其他變量和自己以前的值 —— 在某些情況下可以使用 volatile 代替 synchronized 來簡化代碼。然而,使用 volatile 的代碼往往比使用鎖的代碼更加容易出錯。本文介紹的模式涵蓋了可以使用 volatile 代替 synchronized 的最常見的一些用例。遵循這些模式(注意使用時不要超過各自的限制)可以幫助您安全地實現大多數用例,使用 volatile 變量獲得更佳性能。

原文地址:https://www.cnblogs.com/CBDoctor/p/5143111.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 鸭子玩富婆流白浆视频 | 2014天堂 | 99色亚洲| 国产性做久久久久久 | 色婷婷综合缴情综六月 | 2021最新国产成人精品视频 | 91精品久久一区二区三区 | 国产亚洲女在线精品 | 99精品视频在线观看免费 | 乌克兰xxxxx 我要色色网 | 国产一区二区三区久久精品小说 | 国产一区视频在线免费观看 | 五月色婷婷网在线观看 | 国产精品久久久久久久久免费 | 久久婷婷电影网 | 四虎永久 | 范冰冰a级一级特级毛片 | 国产精品合集一区二区 | 四虎成人免费 | 免费在线看片网站 | 男人的j进入女人的j免费 | 国产精品亚洲精品日韩已方 | 互换身体全集免费观看 | 久久精品国产色蜜蜜麻豆国语版 | 白丝爆动漫羞羞动漫网站 | 免费片在线观看 | 交换朋友夫妇3中文字幕 | 美女被狂揉下部羞羞动漫 | 免费亚洲视频在线观看 | 九九精品久久 | 免费看日本 | a∨在线观看 | 国产成人一区二区三区在线视频 | 亚洲一区二区成人 | 欧美二区三区 | meyd–456佐山爱在线播放 | 久久精品嫩草影院免费看 | 欧美日韩一区二区三在线 | 久久re亚洲在线视频 | 精品在线99| 99成人国产精品视频 |