這是一個(gè)老生常談的面試題了顶考,wait
和 notify
配合監(jiān)視器提供了多個(gè)同步線程之間通信機(jī)制并思,答案本身也很簡(jiǎn)單暇韧,由于通信本身解決的就是鎖的歸屬問(wèn)題(發(fā)現(xiàn)當(dāng)前應(yīng)該把鎖給別人時(shí)調(diào)用 wait
, 通知?jiǎng)e人可以來(lái)用鎖了調(diào)用 notify
)轧坎,從功能上講爪喘,放在 Object
類(鎖對(duì)象)中本就是理所當(dāng)然的颜曾。
但我們可以換個(gè)角度去思考,不妨使用假設(shè)法秉剑,假設(shè) wait
和 notify
是放在 Thread
類中泛豪,看看使用的情況會(huì)是怎么樣的。
由于線程之間并不知道其他對(duì)象獲取鎖的情況,需要額外的開(kāi)銷去記錄和遍歷其他線程的情況诡曙,并且一個(gè)線程實(shí)際上是可以擁有多個(gè)鎖的吕粹。因此,要實(shí)現(xiàn)線程通信機(jī)制岗仑,有兩個(gè)必不可少的參數(shù)匹耕,線程和鎖對(duì)象。
synchronized(lock) {
Thread.currentThread().wait(lock);
}
如果是這么使用的話其實(shí)沒(méi)有什么問(wèn)題荠雕,從功能上來(lái)說(shuō)其實(shí)和 lock.wait()
沒(méi)有什么區(qū)別稳其。但是,只要有存在的可能炸卑,就一定會(huì)發(fā)生既鞠。有些人可能剛好由于契合某些業(yè)務(wù)來(lái)實(shí)現(xiàn)某些功能會(huì)寫(xiě)出以下代碼:
List<Thread> threadList = ...
synchronized(lock) {
threadList.get(i).wait(lock);
}
在當(dāng)前線程的代碼允許其他的線程在所需的鎖上等待,這種“入侵”式的代碼給設(shè)計(jì)和維護(hù)帶來(lái)了許多的困難盖文,原本并發(fā)程序就不好調(diào)式嘱蛋,這樣一來(lái)就更加的混亂,并且產(chǎn)生無(wú)法預(yù)計(jì)和復(fù)現(xiàn)的錯(cuò)誤五续。畢竟可能讓使用者產(chǎn)生錯(cuò)誤用法的設(shè)計(jì)就不是一個(gè)好的設(shè)計(jì)洒敏。