1 回答

TA貢獻1784條經(jīng)驗 獲得超9個贊
每個鎖對象都有兩個隊列,一個是就緒隊列,一個是阻塞隊列,就緒隊列存儲了將要獲得鎖的線程,阻塞隊列存儲了被阻塞的線程,當一個被線程被喚醒 (notify)后,才會進入到就緒隊列,等待獲得鎖。你說的等待隊列也就是阻塞隊列。
例如:當一開始線程a第一次執(zhí)行對象account.add()方法時,JVM會檢查鎖對象account的就緒隊列是否已經(jīng)有線程在等待,如果有則表明account的鎖已經(jīng)被占用了,由于是第一次運行,account的就緒隊列為空,所以線程a獲得了鎖, 執(zhí)行account.add方法。如果恰好在這個時候,線程b要執(zhí)行account.withdraw方法,因為線程a已經(jīng)獲得了鎖還沒有釋放,所以線程b要進入account的就緒隊列,等到得到鎖后才可以執(zhí)行。一個線程執(zhí)行臨界區(qū)代碼過程如下:
1.獲得同步鎖2.清空工作內(nèi)存3.從主存拷貝變量副本到工作內(nèi)存4.對這些變量計算5.將變量從工作內(nèi)存寫回到主存6.釋放鎖
可見,synchronized既保證了多線程的并發(fā)有序性,又保證了多線程的內(nèi)存可見性。notify 不會釋放鎖,而是通知鎖對象的阻塞隊列里的某一線程(被阻塞,即主動調(diào)用wait方法),進入就緒隊列。線程釋放鎖的方式,通常是 主動調(diào)用wait方法、同步代碼塊結(jié)束釋放鎖資源。notifyall 是 喚醒阻塞隊列里的所有阻塞線程,他們都將進入就緒隊列,而notify的數(shù)量是一個。同步代碼塊結(jié)束釋放鎖資源,對象就緒隊列中的某一線程獲得鎖資源而開始線程;如果不使用notify 那么阻塞隊列 里 線程將一直處于阻塞狀態(tài),即使就緒隊列里 線程都執(zhí)行完了,阻塞隊列 里 線程也將一直處于阻塞狀態(tài).某一線程釋放鎖之后,將會從就緒隊列中 隨機找出?(有疑問) 一線程,使之獲得鎖資源。
添加回答
舉報