Java中volatile實現執行緒間變數共享

2021-09-01 15:50:59 字數 1760 閱讀 4043

[size=medium][b]volatile變數自身具有下列特性:[/b]

可見性。對乙個volatile變數的讀,總是能看到(任意執行緒)對這個volatile變數最後的寫入。

原子性:對任意單個volatile變數的讀/寫具有原子性,但類似於volatile++這種復合操作不具有原子性。

上面講的是volatile變數自身的特性,對程式設計師來說,volatile對執行緒的記憶體可見性的影響比volatile自身的特性更為重要,也更需要我們去關注。

從jsr-133開始,volatile變數的寫-讀可以實現執行緒之間的通訊。

從記憶體語義的角度來說,volatile與監視器鎖有相同的效果:volatile寫和監視器的釋放有相同的記憶體語義;volatile讀與監視器的獲取有相同的記憶體語義。

請看下面使用volatile變數的示例**:[/size]

class volatileexample 

public void reader()

}}

[img]

這裡a執行緒寫乙個volatile變數後,b執行緒讀同乙個volatile變數。a執行緒在寫volatile變數之前所有可見的共享變數,在b執行緒讀同乙個volatile變數後,將立即變得對b執行緒可見。

[b]volatile寫-讀的記憶體語義[/b]

1、volatile寫的記憶體語義如下:

當寫乙個volatile變數時,jmm會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。

以上面示例程式volatileexample為例,假設執行緒a首先執行writer()方法,隨後執行緒b執行reader()方法,初始時兩個執行緒的本地記憶體中的flag和a都是初始狀態。下圖是執行緒a執行volatile寫後,共享變數的狀態示意圖:

[img]

如上圖所示,執行緒a在寫flag變數後,本地記憶體a中被執行緒a更新過的兩個共享變數的值被重新整理到主記憶體中。此時,本地記憶體a和主記憶體中的共享變數的值是一致的。

2、[b]volatile讀的記憶體語義如下:

當讀乙個volatile變數時,jmm會把該執行緒對應的本地記憶體置為無效。執行緒接下來將從主記憶體中讀取共享變數。

下面是執行緒b讀同乙個volatile變數後,共享變數的狀態示意圖:

[img]

如上圖所示,在讀flag變數後,本地記憶體b已經被置為無效。此時,執行緒b必須從主記憶體中讀取共享變數。執行緒b的讀取操作將導致本地記憶體b與主記憶體中的共享變數的值也變成一致的了。

如果我們把volatile寫和volatile讀這兩個步驟綜合起來看的話,在讀執行緒b讀乙個volatile變數後,寫執行緒a在寫這個volatile變數之前所有可見的共享變數的值都將立即變得對讀執行緒b可見。

[color=red]下面對volatile寫和volatile讀的記憶體語義做個總結:[/color]

執行緒a寫乙個volatile變數,實質上是執行緒a向接下來將要讀這個volatile變數的某個執行緒發出了(其對共享變數所在修改的)訊息。

執行緒b讀乙個volatile變數,實質上是執行緒b接收了之前某個執行緒發出的(在寫這個volatile變數之前對共享變數所做修改的)訊息。

執行緒a寫乙個volatile變數,隨後執行緒b讀這個volatile變數,這個過程實質上是執行緒a通過主記憶體向執行緒b傳送訊息。

由於volatile僅僅保證對單個volatile變數的讀/寫具有原子性,而監視器鎖的互斥執行的特性可以確保對整個臨界區**的執行具有原子性。在功能上,監視器鎖比volatile更強大;在可伸縮性和執行效能上,volatile更有優勢。如果讀者想在程式中用volatile代替監視器鎖,請一定謹慎。[/size]

Java併發 volatile的實現原理

synchronized 是乙個重量級的鎖,volatile通常被比喻成輕量級的synchronized volatile是乙個變數修飾符,只能用來修飾變數。volatile寫 當寫乙個volatile變數時,jmm會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。volatile讀 當讀...

java 中volatile關鍵字

1.volatile關鍵字往往用於多執行緒,保證了執行緒可以正確讀取其他執行緒傳入的值。2.volatile的特殊規則保證了volatile變數值修改後的新值立刻同步到主記憶體,每次使用volatile變數前立即從主記憶體中重新整理,因此volatile保證了多執行緒之間的操作變數的可見性,而普通變...

java中關鍵字volatile

1.用在多執行緒同步變數時,執行緒為了提高效率,將某成員變數 如a 拷貝了乙份 如b 執行緒中對a的訪問其實訪問的是b。只在某些動作時才進行a和b的同步。因此存在a和b不一致的情況。volatile就是用來避免這種情況的。volatile告訴jvm,它所修飾的變數不保留拷貝,直接訪問主記憶體中的 也...