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