Java鎖事之重量級鎖

Java中的重量級鎖是通過ObjectMonitor實現(xiàn)的。接下來簡單分析下ObjectMonitor的實現(xiàn)邏輯。

Objectmonitor中的關(guān)鍵詞

  • EntryList
  • WaitList
  • cxq(ContentionList)
  • Owner
  • OnDeckThread
  • recursions

cxq(競爭列表)

cxq是一個單向鏈表。被掛起線程等待重新競爭鎖的鏈表, monitor 通過CAS將包裝成ObjectWaiter寫入到列表的頭部。為了避免插入和取出元素的競爭,所以O(shè)wner會從列表尾部取元素。

重量級鎖3.jpg

EntryList(鎖候選者列表)

EntryList是一個雙向鏈表。當(dāng)EntryList為空,cxq不為空,Owener會在unlock時,將cxq中的數(shù)據(jù)移動到EntryList。并指定EntryList列表頭的第一個線程為OnDeck線程。

EntryList跟cxq的區(qū)別

在cxq中的隊列可以繼續(xù)自旋等待鎖,若達(dá)到自旋的閾值仍未獲取到鎖則會調(diào)用park方法掛起。而EntryList中的線程都是被掛起的線程。

WaitList

WatiList是Owner線程地調(diào)用wait()方法后進(jìn)入的線程。進(jìn)入WaitList中的線程在notify()/notifyAll()調(diào)用后會被加入到EntryList。

Owner

當(dāng)前鎖持有者。

OnDeckThread

可進(jìn)行鎖競爭的線程。若一個線程被設(shè)置為OnDeck,則表明其可以進(jìn)行tryLock操作,若獲取鎖成功,則變?yōu)镺wner,否則仍將其回插到EntryList頭部。

OnDeckThread競爭鎖失敗的原因

cxq中的線程可以進(jìn)行自旋競爭鎖,所以O(shè)nDeckThread若碰上自旋線程就需要和他們競爭

recursions(重入計數(shù)器)

用來表示某個線程進(jìn)入該鎖的次數(shù)。

重量級鎖2.jpg

執(zhí)行流程

獲取monitor

  1. 線程首先通過CAS嘗試將monitor的owner設(shè)置為自己。
  2. 若執(zhí)行成功,則判斷該線程是不是重入。若是重入,則執(zhí)行recursions + 1,否則執(zhí)行recursions = 1。
  3. 若失敗,則將自己封裝為ObjectWaiter,并通過CAS加入到cxq中。

釋放monitor

  1. 判斷是否為重量級鎖,是則繼續(xù)流程。
  2. recursions - 1
  3. 根據(jù)不同的策略設(shè)置一個OnDeckThread

參考

  1. The underlying JVM is how to realize the synchronized

  2. 對象頭

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容