Synchronized鎖原理

Synchronized鎖原理

前情提要

  1. 對於普通同步方法,鎖是當前實例對象。

  2. 對於靜態同步方法,鎖是當前類的Class對象。

  3. 對於同步方法塊,鎖是Synchonized括號裏配置的對象。

Synchonized在JVM裏的實現原理,

JVM基於進入和退出Monitor對 象來實現方法同步和代碼塊同步

Monitor是有monitorenter和monitorexit指令的,線程每次執行到monitorenter,都會嘗試獲取對象的monitor,也就是對象的鎖

鎖的升級

Java對象頭裏的Mark Word裏默認存儲對象的HashCode、分代年齡和鎖標記位。

無鎖狀態、偏向鎖狀態、輕量級鎖狀態和重量級鎖狀態,這幾個狀態會隨着競爭情況逐漸升級。鎖可以升級但不能降級

1. 偏向鎖

爲什麼有偏向鎖概念?

爲了減少獲得鎖和釋放鎖帶來的性能消耗.

那下面來從減少消耗入手來講

大多數情況下,鎖不僅不存在多線程競爭,而且總是由同 一線程多次獲得,爲了讓線程獲得鎖的代價更低而引入了偏向鎖

你可以理解可重入鎖,當進入拿到了鎖再進入其它的就方便了,這裏只是比喻。。不等同

哪些措施減少消耗的(線程ID的檢查)

當一個線程訪問同步塊並 獲取鎖時,會在對象頭和棧幀中的鎖記錄裏存儲鎖偏向的線程ID,下次進入直接測試有無ID記錄,有就簡單了直接盤它!

沒有的話,先看看這是不是偏向鎖,不是就用CAS競爭鎖然後記錄線程ID,是的話就用CAS直接記錄自己的線程ID,

1.1 偏向鎖的撤銷

只要有其它線程競爭偏向鎖,就會釋放鎖,具體流程如下:

線程1拿到偏向鎖在執行,線程2來執行同步方法,先檢查ID,沒有,檢查發現是偏向鎖,CAS記錄自己的線程ID,但在記錄之前需要暫停線程1,然後把線程ID設置爲空,然後就可以設置自己的了

1.2 偏向鎖的意義

偏向鎖,它的目的是消除數據在無競爭的情況下的同步原語,進一步提高程序的運行性能,不用CAS

2. 輕量級鎖

2.1 加鎖

  1. 線程在執行同步塊之前,JVM會先在當前線程的棧楨中創建用於存儲鎖記錄的空間

  2. 拿到鎖記錄指針。將對象頭中的Mark Word複製到鎖記錄中,CAS替換那個markword

  3. 如果成功,當前線程獲得鎖,

  4. 如果失敗,表示其他線程競爭鎖,當前線程便嘗試使用自旋來獲取鎖

2.2 解鎖

  1. 輕量級解鎖時,會使用原子的CAS操作將Displaced Mark Word替換回到對象頭

  2. 如果成功,則表示沒有競爭發生。

  3. 如果失敗,表示當前鎖存在競爭,鎖就會膨脹成重量級鎖

2.3 輕量鎖的意義

輕量級鎖是在無競爭的情況下使用CAS操作去消除同步使用的互斥量

3.鎖的對比

優點 缺點 使用場景
偏向鎖 加鎖和解鎖無消耗,爭取不用CAS 競爭鎖的情況會有撤銷鎖的消耗 適用單線程
輕量級鎖 競爭的線程不會阻塞,利用CAS CAS會自旋消耗CPU 追求響應時間
重量級鎖 不會消耗CPU,直接阻塞對方 線程會阻塞 追求吞吐量,不在乎時間和交互
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章