Java偏向鎖實現原理(Biased Locking)



閱讀本文的讀者,需要對Java輕量級鎖有一定的瞭解,知道lock record, mark word之類的名詞。可以參考我的一篇博文:Java輕量級鎖原理詳解(Lightweight Locking)

Java偏向鎖(Biased Locking)是Java6引入的一項多線程優化。它通過消除資源無競爭情況下的同步原語,進一步提高了程序的運行性能。

輕量級鎖也是一種多線程優化,它與偏向鎖的區別在於,輕量級鎖是通過CAS來避免進入開銷較大的互斥操作,而偏向鎖是在無競爭場景下完全消除同步,連CAS也不執行(CAS本身仍舊是一種操作系統同步原語,始終要在JVM與OS之間來回,有一定的開銷)。

所謂的無競爭場景,舉個例子,就是單線程訪問帶同步的資源或方法。

偏向鎖實現原理

偏向鎖,顧名思義,它會偏向於第一個訪問鎖的線程,如果在接下來的運行過程中,該鎖沒有被其他的線程訪問,則持有偏向鎖的線程將永遠不需要觸發同步。
如果在運行過程中,遇到了其他線程搶佔鎖,則持有偏向鎖的線程會被掛起,JVM會嘗試消除它身上的偏向鎖,將鎖恢復到標準的輕量級鎖。(偏向鎖只能在單線程下起作用)

通過下圖可以更直觀的理解偏向鎖:

這張圖,省略了輕量級鎖相關的幾處步驟,將關注點更多地聚焦在偏向鎖的狀態變化上。
偏向模式和非偏向模式,在下面的mark word表中,主要體現在thread ID字段是否爲空。

掛起持有偏向鎖的線程,這步操作類似GC的pause,但不同之處是,它只掛起持有偏向鎖的線程(非當前線程)。

在搶佔模式的橙色區域說明中有提到,指向當前堆棧中最近的一個lock record(在輕量級鎖原理一文有講到,lock record是進入鎖前會在stack上創建的一份內存空間)。
這裏提到的最近的一個lock record,其實就是當前鎖所在的stack frame上分配的lock record。
整個步驟是從偏向鎖恢復到輕量級鎖的過程。

偏向鎖也會帶來額外開銷

在JDK6中,偏向鎖是默認啓用的。它提高了單線程訪問同步資源的性能。
但試想一下,如果你的同步資源或代碼一直都是多線程訪問的,那麼消除偏向鎖這一步驟對你來說就是多餘的。事實上,消除偏向鎖的開銷還是蠻大的。

所以在你非常熟悉自己的代碼前提下,大可禁用偏向鎖 -XX:-UseBiasedLocking 。

發佈了164 篇原創文章 · 獲贊 26 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章