1 回答

TA貢獻1796條經驗 獲得超4個贊
規格notify()
說:
如果有任何線程在此對象上等待,則選擇其中一個喚醒。該選擇是任意的,并且可以根據實現情況進行選擇。
這意味著您不能期望任何特定的順序,而實現可能會使用它想要的任何特定的順序,包括調用的順序wait
。
沒有理由為什么實現應該實現改組。那只會浪費資源。使實現具有自由的原因是允許他們在適合時使用更高效的算法,而不必維護命令。
因此,由于存儲結構不同,不同的實現可能會以相反的順序喚醒它們。如果實現切換到閾值以上的其他存儲結構,則它也可能隨著一定數量的排隊線程而改變。
除此之外,您的測試代碼非常特別。您的主線程在調用之前會等待很長時間notify()
,因此所有線程可能已經進入等待狀態,并存儲在JVM使用的任何數據結構中。然后,一次只有一個掛起notify()
,因為讓喚醒的線程進行下一個掛起notify()
。如果您允許操作重疊,則圖片可能會發生巨大變化。
然后,可能會發現底層數據結構不是純FIFO。同樣,對于實現來說,wait()
如果有待處理的線程允許線程調用立即繼續進行notify()
,而不考慮等待隊列,而繞過所有已排隊的線程,這是一種安靜的做法,因為這樣做效率更高。
另一點是,如果有多個掛起notify()
,則喚醒的線程必須競爭重新獲取對象監視器。這取決于操作系統的調度程序和實際的系統負載,哪個線程將在此處成功執行,因此,即使按入隊的順序喚醒了這些線程,由于JVM無法控制的詳細信息,線程仍可能在此位置被超越。
另外,請不要忘記規范允許虛假喚醒。因此,一個不能夠單獨喚醒單個線程的JVM可以在notify()
不違反規范的情況下,由于一次調用而喚醒多個線程。
添加回答
舉報