《Java併發編程的藝術》第二章--2.2--synchronized的實現原理與應用

在多線程併發編程中synchronized一直是元老級角色,不少人都會稱呼它爲重量級鎖。但編程

是,隨着Java SE 1.6對synchronized進行了各類優化以後,有些狀況下它就並不那麼重了數組

Java中的每個對象均可以做爲鎖。具體表現爲如下3種形式。多線程

  • 對於普通同步方法,鎖是當前實例對象
  • 對於靜態同步方法,鎖是當前類的Class對象
  • 對於同步方法塊,鎖是Synchonized括號裏配置的對象

當一個線程試圖訪問同步代碼塊時,它首先必須獲得鎖,退出或拋出異常時必須釋放鎖。併發

那麼鎖到底存在哪裏呢?鎖裏面會存儲什麼信息呢?性能

從JVM規範中能夠看到Synchonized在JVM裏的實現原理,JVM基於進入和退出Monitor優化

象來實現方法同步和代碼塊同步,但二者的實現細節不同。代碼塊同步是使用monitorenter線程

和monitorexit指令實現的,而方法同步是使用另一種方式實現的,細節在JVM規範裏並無對象

詳細說明。可是,方法的同步一樣可使用這兩個指令來實現。同步

monitorenter指令是在編譯後插入到同步代碼塊的開始位置,而monitorexit插入到方法結虛擬機

束處和異常處,JVM要保證每一個monitorenter必須有對應的monitorexit與之配對。任何對象都有

一個monitor與之關聯,當且一個monitor被持有後,它將處於鎖定狀態。線程執行到monitorenter

指令時,將會嘗試獲取對象所對應的monitor的全部權,即嘗試得到對象的鎖。

2.2.1 Java對象頭

synchronized用的鎖是存在Java對象頭裏的。若是對象是數組類型,則虛擬機用3個字寬

(Word)存儲對象頭,若是對象是非數組類型,則用2字寬存儲對象頭。在32位虛擬機中,1字寬

等於4字節,即32bit。

2.2.2 鎖的升級與對比

Java SE 1.6爲了減小得到鎖和釋放鎖帶來的性能消耗,引入了「偏向鎖」和「輕量級鎖」,在

Java SE 1.6中,鎖一共有4種狀態,級別從低到高依次是:無鎖狀態、偏向鎖狀態、輕量級鎖狀

態和重量級鎖狀態(這種分類是按照鎖狀態來概括的,而且是針對 synchronized 的),

這幾個狀態會隨着競爭狀況逐漸升級。鎖能夠升級但不能降級,意味着偏

向鎖升級成輕量級鎖後不能降級成偏向鎖。這種鎖升級卻不能降級的策略,目的是爲了提升

得到鎖和釋放鎖的效率。 

以上是synchronized中的一部分,關於「偏向鎖」和「輕量級鎖」的具體內容沒有貼出來,對於synchronized先作簡單瞭解。

相關文章
相關標籤/搜索