併發程式設計時各個執行緒中無法獲取到共享變數的最新值。
共享變數儲存在主記憶體中,通常情況下各個執行緒在使用某個共享變數時先將共享變數複製進執行緒工作記憶體中,後續使用到該變數時直接從當前執行緒工作記憶體中獲取變數值,此時如果其他執行緒更改了該共享變數值那麼當前執行緒無法實時更新到該變數的最新值。
同步互動協議中規定的8種原子操作
如下**while迴圈會一直執行知道cpu達到100%應用程式崩潰
p
rivate static
boolean is=
true
;public
static
void
main
(string[
] args)
system.out.
println
("迴圈終止");
system.out.
println
(i);}}
).start()
;try
catch
(interruptedexception ex)
visibilitydemo.is=
false
; system.out.
println
("被置為false了");
}
final修飾的變數不可變,所以不存在變數可見性問題
synchronized語義規範
解鎖前,必須把共享變數同步回主記憶體
示例
private
static
boolean is=
true
;public
static
void
main
(string[
] args)
} system.out.
println
("迴圈終止");
system.out.
println
("i="
+i);}}
).start()
;try
catch
(interruptedexception ex)
visibilitydemo.is=
false
; system.out.
println
("被置為false了");
}
執行結果
被置為false了
迴圈終止
i=64274144
volatile語義規範
使用volatile變數時,必須重新從主記憶體載入,並且read、load是連續的
修改volatile變數後,必須立馬同步回主記憶體,並且store、write是連續的
示例
private
static
volatile
boolean is=
true
;public
static
void
main
(string[
] args)
system.out.
println
("迴圈終止");
system.out.
println
(i);}}
).start()
;try
catch
(interruptedexception ex)
visibilitydemo.is=
false
; system.out.
println
("被置為false了");
}
執行結果
被置為false了
迴圈終止
-860124361
synchronized使用鎖機制保護共享資源,只有獲得鎖的執行緒才可操作共享資源,同時synchronized語義規範保證了修改共享資源後會同步回主記憶體,從而做到執行緒安全。volatile因為沒有鎖機制,所以執行緒還是可以併發操作變數,所以沒有做到執行緒安全
volatile僅能使用在變數級別;synchronized則可以使用在變數、方法、和類級別的
volatile不會造成執行緒的阻塞;synchronized可能會造成執行緒的阻塞
volatile標記的變數不會被編譯器優化;synchronized標記的變數可以被編譯器優化
015 可見性問題與volatile
一 概述 可見性問題 什麼是可見性問題?可見性問題的原因是什麼?快取之中存在共享變數的副本,在有些時候,因為來不及維護副本和實體的一致性可能造成問題,這種問題就是可見性問題.注意 當我們解決的原子性的同時也就完成了可見性的問題的解決.二 可見性性問題的例子 public class visiable...
JAVA多執行緒 共享變數的可見性問題
我們知道執行緒在工作的時候有自己的私有記憶體,工作記憶體。程式執行的時候從主記憶體拉取需要的變數到工作記憶體,處理完再返回主記憶體。這篇文章總結哪些 會使執行緒去主記憶體拉取變數。volatile修飾的變數,不論什麼語句都會從主記憶體拉取變數。該程式能順利完成,不會死迴圈。因為 isstop 用vo...
驗證Volatile可見性問題的關鍵
關鍵在於 while flag 中不能有從主記憶體讀取的操作 常見的兩種 thread.sleep,觸發了執行緒的重新排程,儲存當前執行緒上下文,即刷到主記憶體。存在synchronized,當獲取鎖以後,清空本地記憶體中共享變數,從主記憶體進行載入,在釋放鎖時將本地記憶體中共享變數重新整理到主記憶...