鎖
-
對於普通同步方法,鎖是當前實例對象
-
對於靜態同步方法,鎖是當前class類對象
-
對於同步方法塊,鎖是括號內對象。
JVM基於進入和退出Monitor對象來實現方法和代碼塊同步。每個java對象都有一個Monitor與之對應。代碼塊同步是用monitorenter和monitorexit關鍵字實現。monitor的本質是依賴於底層操作系統的Mutex Lock實現。
synchronized用的鎖是在Java對象頭裏的。如果對象是數組類型,則虛擬機用3個字寬存儲對象頭。如果對象是非數組類型,則用2個字寬存儲對象頭。在32位虛擬機中,1字寬=4字節(32bit)
對象頭信息
長度 | 內容 | 說明 |
32/64bit |
Mark word |
存儲對象的HashCode或鎖信息 |
同上 |
Class Metadata Adress |
存儲到對象類型數據的指針 |
32bit |
Array length |
數組長度(如果對象是數組) |
mark word在運行期間會隨着鎖標誌位變化而變化。(鎖升級)
鎖升級
JSE1.6做的優化
1.6中鎖一共有4種狀態:
-
無鎖
-
偏向鎖(自旋)
-
輕量級鎖(自旋)
-
重量級鎖
無鎖
無競爭就無鎖
偏向鎖(可重入鎖)
偏向鎖的markWord記錄的是持有鎖的線程id
出現競爭的時候用CAS來獲取鎖。出現競爭就做偏向鎖撤銷邏輯,如果做撤銷操作時,有線程持有偏向鎖,則偏向鎖升級爲輕量級鎖,將Mark word信息修改爲輕量級鎖,並copy到原偏向鎖線程中。
輕量級鎖
CAS操作將對象頭的Mark word中鎖記錄指針指向當前線程鎖記錄。說明哪個線程持有鎖。
CAS操作失敗達到一定次數之後(10?),升級爲重量鎖,等待喚醒。
重量級鎖
mark word指向Monitor對象的指針,互斥鎖,阻塞沒有競爭到鎖的線程