先整理下相關的知識吧。
關於互斥所、自旋鎖
關於常提到的互斥所和自旋鎖,在這篇文章上有詳細的說明,譯文國外的文章,講的很透徹。
http://ifeve.com/practice-of-using-spinlock-instead-of-mutex/
之前理解synchronized用的就是互斥鎖,但其實對於操作系統來說互斥鎖和自旋鎖已經優化到不能分開討論的程度了。
互斥鎖的問題在於:當線程嘗試獲取互斥鎖的時候,如果獲取互斥鎖失敗,則睡眠;等待其他線程釋放鎖后被喚醒,那么問題來了。因為線程的睡眠和喚醒需要調用大量的cpu指令,相對時間開銷比較大。這樣如果一些資源本身被鎖定的時間其實很短,甚至比睡眠和喚醒線程的時間還短,那么使用互斥鎖就很浪費時間和性能。
自旋鎖的問題在於:當線程嘗試獲取自旋鎖的時候,如果獲取自旋鎖失敗,該線程會一直嘗試獲取自旋鎖,直到成功獲取自旋鎖。那么問題來了。如果某個線程占有自旋鎖的時間較長,那么其他嘗試獲取自旋鎖的線程一直在嘗試獲取,並占用cpu操作時間,那么就很不划算,這個時候讓嘗試獲取自旋鎖的線程睡眠就是一個比較好的選擇了。
分析下來也就是說:當資源占用時間較短的時候,自旋鎖是比較優的選擇。當資源占用時間較長的時候,互斥鎖是比較優的選擇。
上邊鏈接文章中也指出,其實現在操作系統的做法通常自旋鎖和互斥鎖已經混合使用了。文章的結論是,大部分時間就直接使用互斥鎖好了,因為現在大多數操作系統在獲得互斥鎖之前都會自旋一段時間(混合型互斥鎖),只有在你覺得某個場景下,使用自旋鎖替確實能提高性能,則可以自己嘗試使用自旋鎖,並且還要考慮單核系統還是多核系統亦或是分布式系統,總之使用之前一定要做好相關的測試工作。
上邊整理了下那篇文章中關於互斥鎖、自旋鎖的內容,比較偏向理論了。
關於cpu緩存一致性
緩存一致性參照infoQ的文章;http://www.infoq.com/cn/articles/cache-coherency-primer
關於這個緩存一致性的知識,只作為知曉;
主要的就是MESI協議。詳細內容請查看文章,我自己做的總結就是。
首先結構上cpu對內存的操作,在現在操作系統中,cpu不能直接操作內存,而是通過一級緩存、二級緩存甚至三級緩存操作。數據操作是cpu通過緩存操作內存的。而緩存對內存的操作還要通過總線進行傳輸。所有內存的操作都是通過總線進行的,緩存是獨立的,但內存是共享的。所有的內存訪問都要經過仲裁(arbitrate):同一個指令周期中,只有一個緩存可以讀寫內存。
而保障緩存一致性的現代計算機協議大多都是“窺探”協議,還有一種在很多個cpu場景下才用到的基於目錄的協議。
窺探協議的原理是:緩存並不是只有在讀寫操作的時候,才跟總線打交道,而是不停的窺探總線發生的數據交換,跟蹤其他緩存在干什么,也就是說當一個緩存通過總線讀寫內存的時候,其他緩存都會知道,那么就會根據操作的內存區域,檢查自己的緩存中是否有該段內存,如果發現已經被修改,就將自己的緩存置為無效。這樣就保障了緩存跟內存的實時對應關系。
關於緩存的定律:
基本定律:在任意時刻,任意級別緩存中的緩存段的內容,等同於它對應的內存中的內容。
回寫定律:當所有的臟段被回寫后,任意級別緩存中的緩存段的內容,等同於它對應的內存中的內容。
MESI定律:在所有的臟緩存段(M狀態)被回寫后,任意緩存級別的所有緩存段中的內容,和它們對應的內存中的內容一致。此外,在任意時刻,當某個位置的內存被一個處理器加載入獨占緩存段時(E狀態),那它就不會再出現在其他任何處理器的緩存中。
MESI協議的內容這里不再贅述,文章中有可以查看。
MESI協議規定內存擁有4中狀態(衍生協議可能添加但這4種是必須的):
Invalid 失效緩存段、Shared 共享緩存段、Exclusive 獨占緩存段、Modified已修改緩存段。如果緩存L需要對某一段內存寫操作,而它並沒有獨占權,那么它需要發出一條“我要獨占權”的消息給總線,其他處理器看到后,就會把同段緩存置為無效。而當處理器需要讀取某段緩存時,緩存段的狀態必須為共享狀態,那么其他還沒有回寫的緩存段就需要先把數據回寫到內存,要讀取的處理器,才能從緩存中讀取相應的緩存段。這樣就保證了緩存一致性。
下邊介紹下java鎖升級這塊兒東西,然后整理下CAS用到的cpu鎖的內容。
下面引用下oracle的官方文檔:
Fast Locking in the Java HotSpot VM
* 在java HotSpot虛擬機中實現輕量級鎖包含幾個實用的不變量
不知道其他的虛擬機是否包含這些不變量
* 簡化了偏向鎖算法
* 優化了對象鎖在線程間的傳輸
* HotSpot java虛擬機實用一個兩個字(two words)的對象頭
* Mark word (對象頭)
> 同步,GC和哈希code信息
* Class pointer 類指針
> 對象類型 (Type of object)
> 快速的鎖操作拷貝mark word 到當前激活線程的棧的鎖記錄中
> 鎖記錄管理跟