Every object, in addition to having an associated monitor, has an associated wait set. A wait set is a set of threads.注意一個monitor一個wait set。有兩個東西 安全
When an object is first created, its wait set is empty. Elementary actions that add threads to and remove threads from wait sets are atomic. Wait sets are manipulated solely through the methods Object.wait,Object.notify, and Object.notifyAll. oop
Wait set manipulations can also be affected by the interruption status of a thread, and by the Thread class's methods dealing with interruption. Additionally, the Thread class's methods for sleeping and joining other threads have properties derived from those of wait and notification actions. ui
Wait actions occur upon invocation of wait(), or the timed forms wait(long millisecs) and wait(long millisecs, int nanosecs). this
A call of wait(long millisecs) with a parameter of zero, or a call of wait(long millisecs, int nanosecs) with two zero parameters, is equivalent to an invocation of wait(). atom
A thread returns normally from a wait if it returns without throwing an InterruptedException. spa
Let thread t be the thread executing the wait method on object m, and let n be the number of lock actions by t onm that have not been matched by unlock actions. One of the following actions occurs: 線程
If n is zero (i.e., thread t does not already possess the lock for target m), then anIllegalMonitorStateException is thrown. orm
If this is a timed wait and the nanosecs argument is not in the range of 0-999999 or the millisecsargument is negative, then an IllegalArgumentException is thrown. 對象
If thread t is interrupted, then an InterruptedException is thrown and t's interruption status is set to false. 事件
Otherwise, the following sequence occurs:
Thread t is added to the wait set of object m, and performs n unlock actions on m. --加入等待集;解鎖(N次;計數器清零!)這是惟一的動做,剩下的動做由其它線程引發。
Thread t does not execute any further instructions until it has been removed from m's wait set. The thread may be removed from the wait set due to any one of the following actions, and will resume sometime afterward:
A notify action being performed on m in which t is selected for removal from the wait set. --1被notify選中
If this is a timed wait, an internal action removing t from m's wait set that occurs after at leastmillisecs milliseconds plus nanosecs nanoseconds elapse since the beginning of this wait action. --4被超時事件釋放
An internal action by the implementation. Implementations are permitted, although not encouraged, to perform "spurious wake-ups", that is, to remove threads from wait sets and thus enable resumption without explicit instructions to do so. --5被虛擬機釋放
Notice that this provision necessitates the Java coding practice of using wait only within loops that terminate only when some logical condition that the thread is waiting for holds.
Each thread must determine an order over the events that could cause it to be removed from a wait set. 每一個線程必須爲全部可能將它解釦的事件肯定一個順序。That order does not have to be consistent with other orderings, but the thread must behave as though those events occurred in that order.而後線程必須假定事件將會以這個順序發生。------解釋:1事件是原子的;2事件s必以必定的順序發生;3這是對虛擬機線程實現的要求:沒有同時這一說,必須提供一個順序!!!注意下面的wait, notify, imterrupt交互部分的內容其實已經由這個決定。
For example, if a thread t is in the wait set for m, and then both an interrupt of t and a notification of moccur, there must be an order over these events. If the interrupt is deemed to have occurred first, then t will eventually return from wait by throwing InterruptedException, and some other thread in the wait set for m (if any exist at the time of the notification) must receive the notification. If the notification is deemed to have occurred first, then t will eventually return normally from wait with an interrupt still pending.
If thread t was removed from m's wait set in step 2 due to an interrupt, then t's interruption status is set to false and the wait method throws InterruptedException.---若是是由interrupt釋放的,那麼如今(才)丟出異常。ps: 1:加鎖後的第一個動做;2發生在線程被喚醒之後。順序 扣入-解鎖-解釦-加鎖-異常(若是有)。鎖與等待集不是一個東西。
Notification actions occur upon invocation of methods notify and notifyAll.
Let thread t be the thread executing either of these methods on object m, and let n be the number of lock actions by t on m that have not been matched by unlock actions. One of the following actions occurs:
If n is zero, then an IllegalMonitorStateException is thrown.
This is the case where thread t does not already possess the lock for target m.
If n is greater than zero and this is a notify action, then if m's wait set is not empty, a thread u that is a member of m's current wait set is selected and removed from the wait set.僅此而已,沒有別的。沒有釋放鎖的動做。wait釋放鎖,notify不釋放鎖! 因此關於wait, notify 關鍵的是這個wait set,進入表明扣下,放出表明不扣下。不扣下不必定運行,不必定獲得鎖,不扣下只表明不扣下!!!
There is no guarantee about which thread in the wait set is selected. This removal from the wait set enablesu's resumption in a wait action. Notice, however, that u's lock actions upon resumption cannot succeed until some time after 。t fully unlocks the monitor for 在notify的線程釋放鎖以前,任何線程都不可能獲得這個鎖。m.
If n is greater than zero and this is a notifyAll action, then all threads are removed from m's wait set, and thus resume.釋放全部的線程
Notice, however, that only one of them at a time will lock the monitor required during the resumption of wait.只有一我的能搶到鎖。
Interruption actions occur upon invocation of Thread.interrupt, as well as methods defined to invoke it in turn, such as ThreadGroup.interrupt.
Let t be the thread invoking u.interrupt, for some thread u, where t and u may be the same. This action causes u's interruption status to be set to true.
Additionally, if there exists some object m whose wait set contains u, then u is removed from m's wait set. This enables u to resume in a wait action, in which case this wait will, after re-locking m's monitor, throwInterruptedException. ---四點:1移出waiting set;2可能灰resume;3可能會re-locking;4若是獲得鎖,會丟出interruptedexception
Invocations of Thread.isInterrupted can determine a thread's interruption status. The static methodThread.interrupted may be invoked by a thread to observe and clear its own interruption status.
The above specifications allow us to determine several properties having to do with the interaction of waits, notification, and interruption.上面的規範其實已經決定了如下的性質(關於wait,notify,interrupt交互)
If a thread is both notified and interrupted while waiting, it may either:---若是一個線程同時被通知與中斷,那麼他要麼:
The thread may not reset its interrupt status and return normally from the call to wait.------語義要求不容許中斷被置位與正常返回同時存在。即中斷不能丟失
一樣地,中斷也不能致使通知的丟失。若是一個對象被通知,那麼(語言實現者必須選擇一個實現):Similarly, notifications cannot be lost due to interrupts. Assume that a set s of threads is in the wait set of an objectm, and another thread performs a notify on m. Then either:
at least one thread in s must return normally from wait, or---1必須至少有一個線程正常退出。或者
all of the threads in s must exit wait by throwing InterruptedException---2這個就野了!全部線程異常退出!!!!!!!!!, 注意,若是一個線程先被中斷那麼後面的通知就跟它無關了。被通知的線程能夠被中斷可是一個被中斷的線程已經不在等待集wait set中因此不可能被通知,那麼這個通知就必須被髮給別的線程所以提供了第一個「要麼」, 可是另外一個沒有辦法理解。。。。。。。瘋了嗎? 繼續。這裏要考慮通知與異常的語義。用戶對中斷異常與正常的wait返回可能具備不一樣的處理,而同時出現的中斷與通知,若是被視爲是一個問題的話(由於異常致使了一個多餘原本被扣線程的出列,見本文末端,這個可能打亂原來的信號量通訊歩驟)那麼顯然以異常方式"通知"用戶比仍然堅持notify要好得多,由於notify無疑將使用戶對底下發生的亊情毫無所知繼而使程序產生嚴重的錯誤。換句話說,打亂用戶的信號量與讓他知道發生了錯誤,你選一個吧"!------這個繼續分析真像沒意義,wait與notify就是陀屎!
Note that if a thread is both interrupted and woken via notify, and that thread returns from wait by throwing anInterruptedException, then some other thread in the wait set must be notified.
若是一個線程同時被interrupt與notify,那麼它:要麼帶個異常-interruptedexception-跳出來;要麼被置位-interrupted爲true-跳出來。即線程自己是線程安全的:要麼notify在前(interrupt在後)要麼interrupt在前(notify在後)。兩件事情不會同時發生。
注意若是interrupt在前,就不存在此線程的notify事件由於線程已經被interrupted from the waiting status.即waiting set中已經被拿掉了這個線程。因此interrupt確定拿掉一個waiting 線程。notify也至少拿掉一個waiting線程。因此後面的notify必須被派送到等待此對象的其它線程。