個人筆記--內存可見性和原子變量
阿新 • • 發佈:2018-04-29
ati 方法 發包 加鎖 lag 速度 簡單的 tac png
jdk1.6以後提供了java並發包。
volatile與內存可見性:
例子:
結果:
結論:
main()線程讀取到的td.isFlag並不是true。
這就涉及到了內存可見性問題。
具體原因:
重排序:代碼書寫的順序與實際執行的順序不同。
1. 編譯器重排序
2. 指令重排序
3. 內存系統重排序
As-if-serial:
無論如何重排序,程序執行的記過應該與代碼順序執行的結果一致。Java編譯器和處理器在運行時都會保證在單線程下遵循這個語言。
補充:jstack可以生成線程快照(jdk/bin)
每一個線程都有單獨的內存,只有對一個共享數據進行了操作修改後,才會把更新後的值刷新到主內存中。
但是本例子中,我們使用的是while(true),它的運行速度很快,導致main線程沒能讀取到線程1修改的值便結束了。於是產生了上面的結果。
這就是內存可見性問題-->當多個線程操作共享數據時,彼此不可見。
解決方法1:
加鎖,但是效率太低下了,而且還有其他原因。
這種情況下,我們就可以使用volatile關鍵字了。
可以把它簡單的理解,volatile關鍵字修飾的變量,就存在主內存中。
原子變量和CAS算法:
結果:
原因:
因為i++有三個步驟 所以這時候不能使用volatile關鍵字修飾(放在主緩存中 問題還在) 他只能保證內存可見性問題 不能保證原子性問題
解決方法:
也是一種無鎖的非阻塞算法的實現。
於是改為下面這種:
個人筆記--內存可見性和原子變量