鎖的內存語義

鎖是Java併發編程中最重要的同步機制。鎖除了讓臨界區互斥執行外,還能夠讓釋放鎖的線程向獲取同一個鎖的線程發送消息。java

鎖的獲取和釋放

線程釋放鎖時,JMM會把該線程對應的本地內存中的共享變量刷新到主內存中。編程

線程獲取鎖時,JMM會把該線程對應的本地內存置爲無效。從而使得被監視器保護的臨界區代碼必須從主內存中讀取共享變量。數據結構

在共享變量的可見性方面,鎖的釋放和獲取和volatile是相似的。併發

對volatile變量進行寫操做,JMM會把該線程對應的本地內存中的共享變量刷新到主內存中。atom

對volatile變量進行讀操做,JMM會把該線程對應的本地內存置爲無效。再從主內存中讀取共享變量。線程

 

鎖獲取和釋放內存處理流程:blog

  • 線程A釋放一個鎖,實質上是線程A向接下來將要獲取這個鎖的某個線程發出了(線程A對共享變量所作修改的)消息。
  • 線程B獲取一個鎖,實質上是線程B接收了以前某個線程發出的(在釋放這個鎖以前對共享變量所作修改的)消息。
  • 線程A釋放鎖,隨後線程B獲取這個鎖,這個過程實質上是線程A經過主內存向線程B發送消息。

 

concurrent包的實現

因爲Java的CAS同時具備volatile讀和volatile寫的內存語義,所以Java線程之間的通訊如今有了下面4種方式。
1)A線程寫volatile變量,隨後B線程讀這個volatile變量。
2)A線程寫volatile變量,隨後B線程用CAS更新這個volatile變量。
3)A線程用CAS更新一個volatile變量,隨後B線程用CAS更新這個volatile變量。
4)A線程用CAS更新一個volatile變量,隨後B線程讀這個volatile變量。內存

Java的CAS會使用現代處理器上提供的高效機器級別的原子指令,這些原子指令以原子方式對內存執行讀-改-寫操做,這是在多處理器中實現同步的關鍵。同時,volatile變量的讀/寫和CAS能夠實現線程之間的通訊。把這些特性整合在一塊兒,就造成了整個concurrent包得以實現的基石。同步

分析concurrent包的源代碼實現,會發現一個通用化的實現模式。基礎

首先,聲明共享變量爲volatile。
而後,使用CAS的原子條件更新來實現線程之間的同步。同時,配合以volatile的讀/寫和CAS所具備的volatile讀和寫的內存語義來實現線程之間的通訊。

AQS,非阻塞數據結構和原子變量類(java.util.concurrent.atomic包中的類),這些concurrent包中的基礎類都是使用這種模式來實現的,而concurrent包中的高層類又是依賴於這些基礎類來實現的。

                    concurrent包的實現示意圖

 

 

 

 

 

 

參考:

《Java併發編程藝術》

相關文章
相關標籤/搜索