1. 程式人生 > >volatile的作用和原理

volatile的作用和原理

res 變量 類型 完成 store 使用 use 處理 ava

1、保持內存可見性
內存可見性:所有線程都能看到共享內存的最新狀態。每次讀取前必須先從主內存刷新最新的值。每次寫入後必須立即同步回主內存當中。
Java通過幾種原子操作完成工作內存和主內存的交互:
lock:作用於主內存,把變量標識為線程獨占狀態。
unlock:作用於主內存,解除獨占狀態。
read:作用主內存,把一個變量的值從主內存傳輸到線程的工作內存。
load:作用於工作內存,把read操作傳過來的變量值放入工作內存的變量副本中。
use:作用工作內存,把工作內存當中的一個變量值傳給執行引擎。
assign:作用工作內存,把一個從執行引擎接收到的值賦值給工作內存的變量。
store:作用於工作內存的變量,把工作內存的一個變量的值傳送到主內存中。
write:作用於主內存的變量,把store操作傳來的變量的值放入主內存的變量中。
volatile如何保持內存可見性
volatile的特殊規則就是:
read、load、use動作必須連續出現。
assign、store、write動作必須連續出現。
所以,使用volatile變量能夠保證:
每次讀取前必須先從主內存刷新最新的值。每次寫入後必須立即同步回主內存當中。也就是說,volatile關鍵字修飾的變量看到的隨時是自己的最新值。

2、防止指令重排
volatile關鍵字提供內存屏障的方式來防止指令被重排,編譯器在生成字節碼文件時,會在指令序列中插入內存屏障來禁止特定類型的處理器重排序。
基於保守策略的JMM內存屏障插入策略:
在每個volatile寫操作的前面插入一個StoreStore屏障。
在每個volatile寫操作的後面插入一個StoreLoad屏障。
在每個volatile讀操作的後面插入一個LoadLoad屏障。
在每個volatile讀操作的後面插入一個LoadStore屏障。

對volatile變量的單次讀/寫操作可以保證原子性的,如long和double類型變量,但是並不能保證i++這種操作的原子性,因為本質上i++是讀、寫兩次操作。

volatile不能完全取代Synchronized的位置,只有在一些特殊的場景下,才能適用volatile。總的來說,必須同時滿足下面兩個條件才能保證在並發環境的線程安全:
(1)對變量的寫操作不依賴於當前值。
(2)該變量沒有包含在具有其他變量的不變式中。

volatile的作用和原理