在多線程併發編程中synchronized一直是元老級角色,不少人都會稱呼它爲重量級鎖。但編程
是,隨着Java SE 1.6對synchronized進行了各類優化以後,有些狀況下它就並不那麼重了數組
Java中的每個對象均可以做爲鎖。具體表現爲如下3種形式。多線程
當一個線程試圖訪問同步代碼塊時,它首先必須獲得鎖,退出或拋出異常時必須釋放鎖。併發
那麼鎖到底存在哪裏呢?鎖裏面會存儲什麼信息呢?性能
從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先作簡單瞭解。