Java并發(fā)機制的底層實現(xiàn)原理

volatile的應用


Java編程語言允許線程訪問共享變量,為了確保共享變量能被準確和一致地更新,線程應該確保通過排他鎖單獨獲得這個變量。Java提供了volatile,在某些情況下比鎖要更加方便。如果一個字段被聲明成volatile,Java線程內存模型確保所有線程看到這個變量的值是一致的。

volatile是如何保證可見性的呢?讓我們在X86處理器下通過工具獲取JIT編譯器生成的匯編指令來查看對volatile進行寫操作時,CPU會做什么事。

Java代碼如下:

instance = new Singleton();   //instance是volatile變量

轉成匯編代碼,如下:

0x01a3de1d:movb $0x0,0x1104800(%esi);0x01a3de24: lock addl $0x0,(%esp); 

有volatile變量修飾的共享變量進行寫操作的時候會多出第二行匯編代碼,通過查IA-32架構軟件開發(fā)者手冊可知,Lock前綴的指令在多核處理器下會引發(fā)兩件事情。

  1. 將當前處理器緩存行的數(shù)據(jù)寫回系統(tǒng)內存。
  2. 這個寫回內存的操作會使在其他CPU里緩存了該內存地址的數(shù)據(jù)無效。

為了提高處理速度,處理器不直接和內存進行通信,而是先將內存系統(tǒng)的數(shù)據(jù)讀到內部緩存(L1,L2或其他)后再進行操作,但操作完不知道何時會寫到內存。如果聲明了volatile的變量進行寫操作,JVM就會向處理器發(fā)送一條Lock前綴的指令,將這個變量所在緩存行的數(shù)據(jù)寫回系統(tǒng)內存。但是,就算寫回到內存,如果其他處理器緩存的值還是舊的,再執(zhí)行計算操作就會有問題。所以,在多處理器下,為了保證各個處理器的緩存是一致的,就會實現(xiàn)緩存一致性協(xié)議,每個處理器通過嗅探在總線上傳播的數(shù)據(jù)來檢查自己緩存的值是不是過期了,當處理器發(fā)現(xiàn)自己緩存行對應的內存地址被修改,就會將當前處理器的緩存行設置成無效狀態(tài),當處理器對這個數(shù)據(jù)進行修改操作的時候,會重新從系統(tǒng)內存中把數(shù)據(jù)讀到處理器緩存里。

volatile的兩條實現(xiàn)原則:

  1. Lock前綴指令會引起處理器緩存會寫到內存。
  2. 一個處理器的緩存回寫到內存會導致其他處理器的緩存無效。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容