对jvm 同步锁的理解
sychronized是jvm中對線程同步的主要方法和機制。
Thread.sleep是讓線程丟掉cpu分配資源(讓調度器在某時間內不再調度該線程)。
一個對象的鎖只能同時被一個線程所持有。
對于每一個線程都是兩個ObjectMinor list,一個是freelist,一個是usedlist;usedlist是該線程占有那些對象的鎖,一個線程可以占有多個對象的鎖。
jvm ObjectMinor源代碼:
ObjectMonitor() {_header = NULL;//markOop對象頭_count = 0;_waiters = 0,//等待線程數_recursions = 0;//重入次數_object = NULL;//監視器鎖寄生的對象。鎖不是平白出現的,而是寄托存儲于對象中。_owner = NULL;//指向獲得ObjectMonitor對象的線程或基礎鎖_WaitSet = NULL;//處于wait狀態的線程,會被加入到wait set;_WaitSetLock = 0 ;_Responsible = NULL ;_succ = NULL ;_cxq = NULL ;FreeNext = NULL ;_EntryList = NULL ;//處于等待鎖block狀態的線程,會被加入到entry set;_SpinFreq = 0 ;_SpinClock = 0 ;OwnerIsThread = 0 ;// _owner is (Thread *) vs SP/BasicLock_previous_owner_tid = 0;// 監視器前一個擁有者線程的ID}object notify() 隨意獲取(之前調用wait而阻塞的線程)一個線程喚醒去執行,但是去執行不一定是直接獲取這個對象的鎖,或者執行這個對象中方法,只是喚醒而已。但是注意:去執行object.notify的線程必須是獲取該對象object的鎖的線程,否則會爆出IllegalMonitorStateException。因為只有持有該對象的鎖,該線程中的minor usedlist才有該對象的objectminor,才有能力獲取該objectminor中的_WaitSet 等待隊列。
對于ObjectMinor中EntrySet存放的阻塞block隊列,我們是沒有辦法直接喚醒的.
每個object都包含markOop。如下圖所示:
markOopDesc類
openjdk\hotspot\src\share\vm\oops\markOop.hpp下markOopDesc繼承自oopDesc,并拓展了自己的方法monitor(),如下圖
說說EntrySet和waitSet隊列:
(1)所有期待獲得鎖的線程,在鎖已經被其它線程擁有的時候,這些期待獲得鎖的線程就進入了Object Lock的entry set區域。
(2)所有曾經獲得過鎖,但是由于其它必要條件不滿足而需要wait的時候,線程就進入了Object Lock的wait set區域?。
(3)在wait set區域的線程獲得Notify/notifyAll通知的時候,隨機的一個Thread(Notify)或者是全部的Thread(NotifyALL)從Object Lock的wait set區域進入了entry set中。
(4)在當前擁有鎖的線程釋放掉鎖的時候,處于該Object Lock的entryset區域的線程都會搶占該鎖,但是只能有任意的一個Thread能取得該鎖,而其他線程依然在entry set中等待下次來搶占到鎖之后再執行。
當獲取當前鎖的線程離開同步區,對象的鎖值減一,且鎖值為0(鎖可以重復進入,每次進入自加1),那么監視器會釋放信息量,Entry_set隊列中的線程會搶鎖,只有一個線程可以獲取鎖。總結
以上是生活随笔為你收集整理的对jvm 同步锁的理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美丽的龙泉山
- 下一篇: java 中iterator 和 col