鎖是Java併發編程中最重要的同步機制。鎖除了讓臨界區互斥執行外,還能夠讓釋放鎖的線程向獲取同一個鎖的線程發送消息。java
線程釋放鎖時,JMM會把該線程對應的本地內存中的共享變量刷新到主內存中。編程
線程獲取鎖時,JMM會把該線程對應的本地內存置爲無效。從而使得被監視器保護的臨界區代碼必須從主內存中讀取共享變量。數據結構
在共享變量的可見性方面,鎖的釋放和獲取和volatile是相似的。併發
對volatile變量進行寫操做,JMM會把該線程對應的本地內存中的共享變量刷新到主內存中。atom
對volatile變量進行讀操做,JMM會把該線程對應的本地內存置爲無效。再從主內存中讀取共享變量。線程
鎖獲取和釋放內存處理流程:blog
因爲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併發編程藝術》