1. 程式人生 > >java中的notify和notifyAll有什麽區別?

java中的notify和notifyAll有什麽區別?

lock 鎖競爭 article 隨機 html 就會 成功 external notifyall

先說兩個概念:鎖池和等待池

  • 鎖池:假設線程A已經擁有了某個對象(註意:不是類)的鎖,而其它的線程想要調用這個對象的某個synchronized方法(或者synchronized塊),由於這些線程在進入對象的synchronized方法之前必須先獲得該對象的鎖的擁有權,但是該對象的鎖目前正被線程A擁有,所以這些線程就進入了該對象的鎖池中。
  • 等待池:假設一個線程A調用了某個對象的wait()方法,線程A就會釋放該對象的鎖後,進入到了該對象的等待池中
Reference:java中的鎖池和等待池

鏈接:https://www.zhihu.com/question/37601861/answer/145545371

然後再來說notify和notifyAll的區別

  • 如果線程調用了對象的 wait()方法,那麽線程便會處於該對象的等待池中,等待池中的線程不會去競爭該對象的鎖
  • 當有線程調用了對象的 notifyAll()方法(喚醒所有 wait 線程)或 notify()方法(只隨機喚醒一個 wait 線程),被喚醒的的線程便會進入該對象的鎖池中,鎖池中的線程會去競爭該對象鎖。也就是說,調用了notify後只要一個線程會由等待池進入鎖池,而notifyAll會將該對象等待池內的所有線程移動到鎖池中,等待鎖競爭
  • 優先級高的線程競爭到對象鎖的概率大,假若某線程沒有競爭到該對象鎖,它還會留在鎖池中,唯有線程再次調用 wait()方法,它才會重新回到等待池中。而競爭到對象鎖的線程則繼續往下執行,直到執行完了 synchronized 代碼塊,它會釋放掉該對象鎖,這時鎖池中的線程會繼續競爭該對象鎖。
Reference:線程間協作:wait、notify、notifyAll

綜上,所謂喚醒線程,另一種解釋可以說是將線程由等待池移動到鎖池,notifyAll調用後,會將全部線程由等待池移到鎖池,然後參與鎖的競爭,競爭成功則繼續執行,如果不成功則留在鎖池等待鎖被釋放後再次參與競爭。而notify只會喚醒一個線程。

有了這些理論基礎,後面的notify可能會導致死鎖,而notifyAll則不會的例子也就好解釋了

java中的notify和notifyAll有什麽區別?