1. 程式人生 > >個人筆記--內存可見性和原子變量

個人筆記--內存可見性和原子變量

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關鍵字修飾(放在主緩存中 問題還在) 他只能保證內存可見性問題 不能保證原子性問題

解決方法:

技術分享圖片

也是一種無鎖的非阻塞算法的實現。

於是改為下面這種:

技術分享圖片

個人筆記--內存可見性和原子變量