wait()、notify、notifyAll()的使用


wait()、notify、notifyAll()的使用

參考:https://www.jianshu.com/p/25e243850bd2?appinstall=0

一)、java 中對象鎖的模型

JVM會為一個使用內部鎖(synchronized)的對象維護兩個集合,Entry Set和Wait Set,即鎖池和等待池。

二)、Entry Set:*

如果線程A已經持有了對象鎖,此時如果有其他線程也想獲得該對象鎖的話,它只能進入Entry Set,並且處於線程的BLOCKED狀態。

可能進入Entey Set的線程:

1).兩個搶奪cpu的線程未搶奪到的一方。

2).notify()/notifyAll()喚醒卻未搶奪到cpu的線程。

三)、Wait Set:

如果線程A調用了wait()方法,那么線程A會釋放該對象的鎖,進入到Wait Set,並且處於線程的WAITING狀態。

可能進入wait狀態的線程:

1).調用wait()方法。

四)、Runnable狀態的轉變

Entry Set中的線程的狀態為Blocked狀態:

1).當對象鎖被釋放的時候,JVM會喚醒處於Entry Set中的某一個線程,這個線     程的狀態就從BLOCKED轉變為RUNNABLE。

Wait Set中的線程狀態為Waiting狀態:

1)  .當對象的notify()方法被調用時,JVM會喚醒處於Wait Set中的某一個線程,這個線程的狀態就從WAITING轉變為RUNNABLE。

2).當notifyAll()方法被調用時,Wait Set中的全部線程會轉變為RUNNABLE狀態。所有Wait Set中被喚醒的線程會被轉移到Entry Set中。

注:只有處於Runnable狀態的線程才能去競爭鎖,獲取資源。

五)、notify()和notifyAll()的區別

notify()只喚醒一個線程,notifyAll()喚醒Wati Set的所有線程。

六)、使用notify()容易發生死鎖狀態

舉例:生產者和消費者線程

消費一進行消費,判斷buff為空,調用wait()進入等待狀態,消費者二進行消費buff為空,調用wait(),進入等待狀態,生產者一進行生產,buff滿,notify()消費者一,此時生產者二在Entry Set中搶奪到資源,判斷buff滿,進入到wait狀態,消費者一消費資源,notify(),如果喚醒了生產者,繼續生產,若此時生產者一退出了生產,喚醒了消費者二,buffer為空,消費者二進入wait狀態,此時,生產者二和消費者都進入等待狀態,沒有Runable狀態的線程,生產者2和消費者2在Wait Set中互相等待,發生死鎖。

注: 具體代碼參考https://www.jianshu.com/p/25e243850bd2?appinstall=0

七)、wait()、notify、notifyAll()要配合synchonized使用

解釋一下,這里為什么配合synchonized:

1).如果線程要調用對象的wait()方法,必須首先獲得該對象的監視器鎖,調用
 wait()之后當前線程又立即釋放掉鎖,線程隨后進入WAIT_SET(等待池)中。

2).如果線程要調用對象的notify()/notifyAll()方法,也必須先獲得對象的    監視器鎖調用方法之后,立即釋放掉鎖然后處於Wait_set的線程被轉移到      Entry_set(等鎖 池)中去競爭鎖資源.。The Winner Thread,也就是    成功獲得了對象的鎖的線程,就是對象鎖的擁有者,會進入runnable狀態。

3).由於需要獲得鎖之后才能夠調用wait()/notify()方法,因此必須將它們放    到同步代碼塊中.

八)、總結

1).Jvm的內部鎖對象(synchonized)維護兩個集合Entry Set 和 Wait Set。

2).未搶占到cpu資源或被喚醒卻未搶占到cpu資源的線程會放置在Entry Set中。

3).調用wait()方法的線程進入Wait Set。

4).Entry Set集合的線程為Blocked狀態,Wait Set集合中的線程為Waiting狀態。

5).當鎖資源被釋放時,Entry Set的某一個線程狀態會變成Runnable狀態。

6).當調用notify()方法時,Wait Set的的某一線程被喚醒,由waiting狀態轉為Runable狀態,調用 notifyAll()時,Wait Set的所有線程都被喚醒,線程狀態由waiting轉為Runable狀態,並移入Entry Set中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM