对jvm 同步锁的理解
sychronized是jvm中對線程同步的主要方法和機制。
Thread.sleep是讓線程丟掉cpu分配資源(讓調(diào)度器在某時間內(nèi)不再調(diào)度該線程)。
一個對象的鎖只能同時被一個線程所持有。
對于每一個線程都是兩個ObjectMinor list,一個是freelist,一個是usedlist;usedlist是該線程占有那些對象的鎖,一個線程可以占有多個對象的鎖。
jvm ObjectMinor源代碼:
ObjectMonitor() {_header = NULL;//markOop對象頭_count = 0;_waiters = 0,//等待線程數(shù)_recursions = 0;//重入次數(shù)_object = NULL;//監(jiān)視器鎖寄生的對象。鎖不是平白出現(xiàn)的,而是寄托存儲于對象中。_owner = NULL;//指向獲得ObjectMonitor對象的線程或基礎(chǔ)鎖_WaitSet = NULL;//處于wait狀態(tài)的線程,會被加入到wait set;_WaitSetLock = 0 ;_Responsible = NULL ;_succ = NULL ;_cxq = NULL ;FreeNext = NULL ;_EntryList = NULL ;//處于等待鎖block狀態(tài)的線程,會被加入到entry set;_SpinFreq = 0 ;_SpinClock = 0 ;OwnerIsThread = 0 ;// _owner is (Thread *) vs SP/BasicLock_previous_owner_tid = 0;// 監(jiān)視器前一個擁有者線程的ID}object notify() 隨意獲取(之前調(diào)用wait而阻塞的線程)一個線程喚醒去執(zhí)行,但是去執(zhí)行不一定是直接獲取這個對象的鎖,或者執(zhí)行這個對象中方法,只是喚醒而已。但是注意:去執(zhí)行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)所有期待獲得鎖的線程,在鎖已經(jīng)被其它線程擁有的時候,這些期待獲得鎖的線程就進入了Object Lock的entry set區(qū)域。
(2)所有曾經(jīng)獲得過鎖,但是由于其它必要條件不滿足而需要wait的時候,線程就進入了Object Lock的wait set區(qū)域?。
(3)在wait set區(qū)域的線程獲得Notify/notifyAll通知的時候,隨機的一個Thread(Notify)或者是全部的Thread(NotifyALL)從Object Lock的wait set區(qū)域進入了entry set中。
(4)在當(dāng)前擁有鎖的線程釋放掉鎖的時候,處于該Object Lock的entryset區(qū)域的線程都會搶占該鎖,但是只能有任意的一個Thread能取得該鎖,而其他線程依然在entry set中等待下次來搶占到鎖之后再執(zhí)行。
當(dāng)獲取當(dāng)前鎖的線程離開同步區(qū),對象的鎖值減一,且鎖值為0(鎖可以重復(fù)進入,每次進入自加1),那么監(jiān)視器會釋放信息量,Entry_set隊列中的線程會搶鎖,只有一個線程可以獲取鎖。總結(jié)
以上是生活随笔為你收集整理的对jvm 同步锁的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美丽的龙泉山
- 下一篇: java 中iterator 和 col