为什么wait、notify、notifyAll方法定义在Object中而不是Thread类中
多線程概述
Java是一個支持多線程的開發(fā)語言,多線程并發(fā)執(zhí)行任務(wù)可以充分利用CPU資源,提高多任務(wù)并發(fā)執(zhí)行效率(注意區(qū)分:多線程并不會加快任務(wù)的執(zhí)行速度,而是可以充分利用多核CPU讓線程輪流進行工作,達到了一種“同時”工作的效果)。
并發(fā)時的產(chǎn)生問題
多線程在執(zhí)行時,會遇到一些問題,問題的關(guān)鍵原因則是在共享資源的更新操作上容易產(chǎn)生沖突。
解決的方向
解決沖突的方式則是從共享資源的占用機制入手,保證共享資源同一時刻只能被一個線程占用,從而達到數(shù)據(jù)一致。
具體實現(xiàn)方式中的一種
在Java中提供了synchorinzed關(guān)鍵字,在該關(guān)鍵字修飾的代碼內(nèi),稱為同步代碼塊,線程執(zhí)行該區(qū)域代碼需要獲取鎖,在獲取成功之后,其他線程需要等該線程執(zhí)行完畢釋放鎖之后才能獲取到。
wait、notify、notifyAll方法的作用
在同步代碼塊中,可以使用wait、notify來控制當前占用資源的線程進入阻塞隊列與喚醒進入就緒隊列
也就是說,上述兩個方法實際上實現(xiàn)的時線程之間的通信機制,用來通知線程的阻塞與喚醒。
引出問題:為什么定義在Object中而不是Thread類
線程為了進入臨界區(qū)(也就是同步塊內(nèi)),需要獲得鎖并等待鎖可用,它們并不知道也不需要知道哪些線程持有鎖,它們只需要知道當前資源是否被占用,是否可以獲得鎖,所以鎖的持有狀態(tài)應(yīng)該由同步監(jiān)視器來獲取,而不是線程本身。
一個比喻
形象的比喻:一個女孩子同時被10個男孩子追,在同一個時間段內(nèi)只能陪一個男孩子看電影,當其中一個男孩想要邀請女孩看電影時,應(yīng)該由女孩子來通知男孩子,這個時間段可不可以赴約,而不應(yīng)該是男孩子詢問其他情敵抑或是由情敵之間相互通知誰該去赴約(那還不打起來了)。
例子中女孩相當于”共享資源“(每一個男孩機會均等),在Java中是一個對象,男孩子們相當于線程,多個線程之間的通信機制,由共享資源(就是前文所說的同步監(jiān)視器)來實現(xiàn),即將wait、notify、notifyAll方法定義在Object中是最合理的
較詳細的解釋
以下是一篇英文博客的翻譯:
為什么它們不應(yīng)該在Thread類,(我)的一些想法是:
wait和nofity不是常見的普通java方法或同步工具,在Java中它們更多的是實現(xiàn)兩個線程之間的通信機制。
如果不能通過類似synchronized這樣的Java關(guān)鍵字來實現(xiàn)這種機制,那么Object類中就是定義它們最好的地方,以此來使任何Java對象都可以擁有實現(xiàn)線程通信機制的能力。
記住synchronized和wait,notify是兩個不同的問題域,并且不要混淆它們的相似或相關(guān)性。 同步類似競態(tài)條件,是提供線程間互斥和確保Java類的線程安全性的,而wait和notify是兩個線程之間的通信機制。
另一個原因:每個對象都可以作為鎖
在Java中,為了進入臨界區(qū)代碼段,線程需要獲得鎖并且它們等待鎖可用,它們不知道哪些線程持有鎖而它們只知道鎖是由某個線程保持,它們應(yīng)該等待鎖而不是知道哪個線程在同步塊內(nèi)并要求它們釋放鎖。 這個比喻適合等待和通知在object類而不是Java中的線程。
這些只是我的想法為什么wait和notify方法在Object類中聲明,而不是Java中的Thread,當然你可以有不同的觀點。
在現(xiàn)實中,它就是Java不支持操作符重載一樣,只是Java設(shè)計者做的一個設(shè)計決定。 無論如何,如果你有任何其它令人信服的理由請發(fā)布出來。
還有一點需要注意:wait、notify、notifyAll方法只能在同步代碼塊中使用,在非同步代碼塊中會導(dǎo)致異常
因為只有在同步代碼塊中才會涉及到鎖的概念,在非并發(fā)環(huán)境下嘗試操作鎖會導(dǎo)致失敗。
總結(jié)
以上是生活随笔為你收集整理的为什么wait、notify、notifyAll方法定义在Object中而不是Thread类中的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: layer.alert/confirm文
- 下一篇: 互联网晚报 | 12月14日 星期二 |