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.
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.
Wait actions occur upon invocation of wait(), or the timed forms wait(long millisecs) and wait(long millisecs, int nanosecs).
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().
A thread returns normally from a wait if it returns without throwing an InterruptedException.
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.
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选中
A notifyAll action being performed on m. --2被notifyAll释放
An interrupt action being performed on t. --3被interrupt释放。
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.
Thread t performs n lock actions on m.---重新加锁(N次)
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:---如果一个线程同时被通知与中断,那么他要么:
return normally from wait, while still having a pending interrupt (in other words, a call toThread.interrupted would return true)---1带一个挂起的中断被“通知“出等待集
return from wait by throwing an InterruptedException---2异常退出
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必须被派送到等待此对象的其它线程。