Synchronization 原理分析

一、Synchronization原理分析

        Synchronization 鎖原理是對象同步通過Monitor 來實現的,java每個對象都會有Monitor鎖標記,代碼塊同步使用的是MONITORENTER和MONITOREXIT來同步;類似於操作系統的PV操作,MONITORENTER會執行+1操作,而MONITOREXIT會執行-1操作。

二、Synchronization數據存放格式

2.1、數據存放    

Synchronization存放在對象的頭部,總共有兩種類型,分別是對象和數組類型,不同的類型存放的格式有所差異,普通對象類型暫用3字寬,數組類型佔用2字寬,1字寬=4字節=32bit(32位虛擬機),鎖只能升級不能降級,如下圖,偏向鎖升級爲輕量級鎖之後不能在降級爲偏向鎖了。

java對象頭(32位虛擬機)
鎖狀態 25bit 4bit 1bit 2bit
23bit 2bit 是否是偏向鎖 鎖標誌位
無鎖狀態 對象hashCode 對象分代年齡 0 01
輕量級鎖 指向棧中鎖記錄的指針 00
重量級鎖 指向互斥量的指針 10
GC標記      
偏向鎖 線程ID Epoch 對象分代年齡 1 01

 

 

 

 

 

 

 

 

2.2、偏向鎖

從數據結構中可以看出,記錄當前線程訪問的ID,如果同一個線程訪問同一個同步塊時,減少加鎖和解鎖操作,直接使用同步快就可以了,降低了獲取鎖和加鎖的開銷。

偏向鎖不會主動撤銷鎖,只有當其他線程競爭資源的時候纔會釋放鎖,變成無鎖狀態,變成爲無鎖狀態需要當先線程已經執行完了同步塊,否則競爭線程會需要等待資源釋放。一旦鎖資源釋放,會喚醒競爭等待的線程。

偏向鎖調整相關參數設置,關閉延遲:-XX:BiasedLockingStartUpDelay=0;關閉偏向鎖:-XX:UseBiasedLocking=true

2.3、輕量級鎖

加鎖:(1)在當前線程棧幀空間創建存儲對象頭MarkWord空間;(2)複製對象MarkWord至(1)創建的空間;(3)使用CAS操作將對象頭中的MarkWord替換爲指向當前線程所記錄的指針,成功表示獲取鎖,失敗表示爲獲取到鎖。

解鎖:使用CAS將當前線程的棧幀中保存的MarkWord替換,回到原來的對象頭,如果成功,表示當前沒有競爭資源失敗會自旋重新獲取,超過一定閾值之後,會升級爲重量級鎖,輕量級鎖升級爲重量級鎖之後,沒法在降級爲輕量級鎖了

2.3、重量級鎖

有輕量級鎖升級爲重量鎖,其鎖保存了互斥量的指針,並且會阻塞當前線程,當一旦有鎖釋放之後,會喚醒當前阻塞的線程。

2.4、性能場景比較

鎖名稱 優點 缺點
偏向鎖 單個線程獲取鎖無需加鎖和解鎖步驟,降低加鎖和解鎖開銷、使用一個線程多次訪問同步 多個線程或存在鎖競爭,多一個鎖撤銷開銷
輕量級鎖 競爭線程不會阻塞,響應速度快 自旋會消耗CPU資源
重量級鎖 吞吐量高 線程阻塞,響應時間慢

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章