6344935: (spec) clarify specifications for Object.wait overloads

Reviewed-by: dholmes, martin, forax, lancea, mchung
This commit is contained in:
Stuart Marks 2017-10-12 17:58:26 -07:00
parent 848a4d9bae
commit 6c266f7163

View File

@ -307,18 +307,67 @@ public class Object {
public final native void notifyAll();
/**
* Causes the current thread to wait until either another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object, or a
* specified amount of time has elapsed.
* Causes the current thread to wait until it is awakened, typically
* by being <em>notified</em> or <em>interrupted</em>.
* <p>
* The current thread must own this object's monitor.
* In all respects, this method behaves as if {@code wait(0L, 0)}
* had been called. See the specification of the {@link #wait(long, int)} method
* for details.
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor
* @throws InterruptedException if any thread interrupted the current thread before or
* while the current thread was waiting. The <em>interrupted status</em> of the
* current thread is cleared when this exception is thrown.
* @see #notify()
* @see #notifyAll()
* @see #wait(long)
* @see #wait(long, int)
*/
public final void wait() throws InterruptedException {
wait(0L);
}
/**
* Causes the current thread to wait until it is awakened, typically
* by being <em>notified</em> or <em>interrupted</em>, or until a
* certain amount of real time has elapsed.
* <p>
* This method causes the current thread (call it <var>T</var>) to
* place itself in the wait set for this object and then to relinquish
* any and all synchronization claims on this object. Thread <var>T</var>
* becomes disabled for thread scheduling purposes and lies dormant
* until one of four things happens:
* In all respects, this method behaves as if {@code wait(timeout, 0)}
* had been called. See the specification of the {@link #wait(long, int)} method
* for details.
*
* @param timeout the maximum time to wait, in milliseconds
* @throws IllegalArgumentException if the value of {@code timeout} is negative
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor
* @throws InterruptedException if any thread interrupted the current thread before or
* while the current thread was waiting. The <em>interrupted status</em> of the
* current thread is cleared when this exception is thrown.
* @see #notify()
* @see #notifyAll()
* @see #wait()
* @see #wait(long, int)
*/
public final native void wait(long timeout) throws InterruptedException;
/**
* Causes the current thread to wait until it is awakened, typically
* by being <em>notified</em> or <em>interrupted</em>, or until a
* certain amount of real time has elapsed.
* <p>
* The current thread must own this object's monitor lock. See the
* {@link #notify notify} method for a description of the ways in which
* a thread can become the owner of a monitor lock.
* <p>
* This method causes the current thread (referred to here as <var>T</var>) to
* place itself in the wait set for this object and then to relinquish any
* and all synchronization claims on this object. Note that only the locks
* on this object are relinquished; any other objects on which the current
* thread may be synchronized remain locked while the thread waits.
* <p>
* Thread <var>T</var> then becomes disabled for thread scheduling purposes
* and lies dormant until one of the following occurs:
* <ul>
* <li>Some other thread invokes the {@code notify} method for this
* object and thread <var>T</var> happens to be arbitrarily chosen as
@ -327,14 +376,18 @@ public class Object {
* object.
* <li>Some other thread {@linkplain Thread#interrupt() interrupts}
* thread <var>T</var>.
* <li>The specified amount of real time has elapsed, more or less. If
* {@code timeout} is zero, however, then real time is not taken into
* consideration and the thread simply waits until notified.
* <li>The specified amount of real time has elapsed, more or less.
* The amount of real time, in nanoseconds, is given by the expression
* {@code 1000000 * timeout + nanos}. If {@code timeout} and {@code nanos}
* are both zero, then real time is not taken into consideration and the
* thread waits until awakened by one of the other causes.
* <li>Thread <var>T</var> is awakened spuriously. (See below.)
* </ul>
* <p>
* The thread <var>T</var> is then removed from the wait set for this
* object and re-enabled for thread scheduling. It then competes in the
* object and re-enabled for thread scheduling. It competes in the
* usual manner with other threads for the right to synchronize on the
* object; once it has gained control of the object, all its
* object; once it has regained control of the object, all its
* synchronization claims on the object are restored to the status quo
* ante - that is, to the situation as of the time that the {@code wait}
* method was invoked. Thread <var>T</var> then returns from the
@ -343,119 +396,54 @@ public class Object {
* thread {@code T} is exactly as it was when the {@code wait} method
* was invoked.
* <p>
* A thread can also wake up without being notified, interrupted, or
* timing out, a so-called <i>spurious wakeup</i>. While this will rarely
* occur in practice, applications must guard against it by testing for
* the condition that should have caused the thread to be awakened, and
* continuing to wait if the condition is not satisfied. In other words,
* waits should always occur in loops, like this one:
* <pre>
* synchronized (obj) {
* while (&lt;condition does not hold&gt;)
* obj.wait(timeout);
* ... // Perform action appropriate to condition
* }
* </pre>
*
* (For more information on this topic, see section 14.2,
* Condition Queues, in Brian Goetz and others' "Java Concurrency
* in Practice" (Addison-Wesley, 2006) or Item 69 in Joshua
* Bloch's "Effective Java (Second Edition)" (Addison-Wesley,
* A thread can wake up without being notified, interrupted, or timing out, a
* so-called <em>spurious wakeup</em>. While this will rarely occur in practice,
* applications must guard against it by testing for the condition that should
* have caused the thread to be awakened, and continuing to wait if the condition
* is not satisfied. See the example below.
* <p>
* For more information on this topic, see section 14.2,
* "Condition Queues," in Brian Goetz and others' <em>Java Concurrency
* in Practice</em> (Addison-Wesley, 2006) or Item 69 in Joshua
* Bloch's <em>Effective Java, Second Edition</em> (Addison-Wesley,
* 2008).
* <p>
* If the current thread is {@linkplain java.lang.Thread#interrupt() interrupted}
* by any thread before or while it is waiting, then an {@code InterruptedException}
* is thrown. The <em>interrupted status</em> of the current thread is cleared when
* this exception is thrown. This exception is not thrown until the lock status of
* this object has been restored as described above.
*
* <p>If the current thread is {@linkplain java.lang.Thread#interrupt()
* interrupted} by any thread before or while it is waiting, then an
* {@code InterruptedException} is thrown. This exception is not
* thrown until the lock status of this object has been restored as
* described above.
* @apiNote
* The recommended approach to waiting is to check the condition being awaited in
* a {@code while} loop around the call to {@code wait}, as shown in the example
* below. Among other things, this approach avoids problems that can be caused
* by spurious wakeups.
*
* <p>
* Note that the {@code wait} method, as it places the current thread
* into the wait set for this object, unlocks only this object; any
* other objects on which the current thread may be synchronized remain
* locked while the thread waits.
* <p>
* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
* @param timeout the maximum time to wait in milliseconds.
* @throws IllegalArgumentException if the value of timeout is
* negative.
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor.
* @throws InterruptedException if any thread interrupted the
* current thread before or while the current thread
* was waiting for a notification. The <i>interrupted
* status</i> of the current thread is cleared when
* this exception is thrown.
* @see java.lang.Object#notify()
* @see java.lang.Object#notifyAll()
*/
public final native void wait(long timeout) throws InterruptedException;
/**
* Causes the current thread to wait until another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object, or
* some other thread interrupts the current thread, or a certain
* amount of real time has elapsed.
* <p>
* This method is similar to the {@code wait} method of one
* argument, but it allows finer control over the amount of time to
* wait for a notification before giving up. The amount of real time,
* measured in nanoseconds, is given by:
* <blockquote>
* <pre>
* 1000000*timeout+nanos</pre></blockquote>
* <p>
* In all other respects, this method does the same thing as the
* method {@link #wait(long)} of one argument. In particular,
* {@code wait(0, 0)} means the same thing as {@code wait(0)}.
* <p>
* The current thread must own this object's monitor. The thread
* releases ownership of this monitor and waits until either of the
* following two conditions has occurred:
* <ul>
* <li>Another thread notifies threads waiting on this object's monitor
* to wake up either through a call to the {@code notify} method
* or the {@code notifyAll} method.
* <li>The timeout period, specified by {@code timeout}
* milliseconds plus {@code nanos} nanoseconds arguments, has
* elapsed.
* </ul>
* <p>
* The thread then waits until it can re-obtain ownership of the
* monitor and resumes execution.
* <p>
* As in the one argument version, interrupts and spurious wakeups are
* possible, and this method should always be used in a loop:
* <pre>
* <pre>{@code
* synchronized (obj) {
* while (&lt;condition does not hold&gt;)
* while (<condition does not hold> and <timeout not exceeded>) {
* long timeout = ... ; // recompute timeout values
* int nanos = ... ;
* obj.wait(timeout, nanos);
* ... // Perform action appropriate to condition
* }
* ... // Perform action appropriate to condition or timeout
* }
* </pre>
* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
* }</pre>
*
* @param timeout the maximum time to wait in milliseconds.
* @param nanos additional time, in nanoseconds range
* 0-999999.
* @throws IllegalArgumentException if the value of timeout is
* negative or the value of nanos is
* not in the range 0-999999.
* @throws IllegalMonitorStateException if the current thread is not
* the owner of this object's monitor.
* @throws InterruptedException if any thread interrupted the
* current thread before or while the current thread
* was waiting for a notification. The <i>interrupted
* status</i> of the current thread is cleared when
* this exception is thrown.
* @param timeout the maximum time to wait, in milliseconds
* @param nanos additional time, in nanoseconds, in the range range 0-999999 inclusive
* @throws IllegalArgumentException if the value of {@code timeout} is negative,
* or if the value of {@code nanos} is out of range
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor
* @throws InterruptedException if any thread interrupted the current thread before or
* while the current thread was waiting. The <em>interrupted status</em> of the
* current thread is cleared when this exception is thrown.
* @see #notify()
* @see #notifyAll()
* @see #wait()
* @see #wait(long)
*/
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
@ -474,48 +462,6 @@ public class Object {
wait(timeout);
}
/**
* Causes the current thread to wait until another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object.
* In other words, this method behaves exactly as if it simply
* performs the call {@code wait(0)}.
* <p>
* The current thread must own this object's monitor. The thread
* releases ownership of this monitor and waits until another thread
* notifies threads waiting on this object's monitor to wake up
* either through a call to the {@code notify} method or the
* {@code notifyAll} method. The thread then waits until it can
* re-obtain ownership of the monitor and resumes execution.
* <p>
* As in the one argument version, interrupts and spurious wakeups are
* possible, and this method should always be used in a loop:
* <pre>
* synchronized (obj) {
* while (&lt;condition does not hold&gt;)
* obj.wait();
* ... // Perform action appropriate to condition
* }
* </pre>
* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor.
* @throws InterruptedException if any thread interrupted the
* current thread before or while the current thread
* was waiting for a notification. The <i>interrupted
* status</i> of the current thread is cleared when
* this exception is thrown.
* @see java.lang.Object#notify()
* @see java.lang.Object#notifyAll()
*/
public final void wait() throws InterruptedException {
wait(0);
}
/**
* Called by the garbage collector on an object when garbage collection
* determines that there are no more references to the object.