changeset 47443:0c2e5ef6a1c6

6344935: (spec) clarify specifications for Object.wait overloads Reviewed-by: dholmes, martin, forax, lancea, mchung
author smarks
date Thu, 12 Oct 2017 17:58:26 -0700
parents b87d7b5d5ded
children 09d386ddaa42
files src/java.base/share/classes/java/lang/Object.java
diffstat 1 files changed, 113 insertions(+), 167 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/Object.java	Thu Oct 12 10:28:20 2017 -0700
+++ b/src/java.base/share/classes/java/lang/Object.java	Thu Oct 12 17:58:26 2017 -0700
@@ -307,18 +307,67 @@
     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 @@
      * 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 @@
      * 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>
+     * 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.
+     *
+     * @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.
+     *
+     * <pre>{@code
      *     synchronized (obj) {
-     *         while (&lt;condition does not hold&gt;)
-     *             obj.wait(timeout);
-     *         ... // Perform action appropriate to condition
+     *         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 or timeout
      *     }
-     * </pre>
+     * }</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,
-     * 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.  This exception is not
-     * thrown until the lock status of this object has been restored as
-     * described above.
-     *
-     * <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>
-     *     synchronized (obj) {
-     *         while (&lt;condition does not hold&gt;)
-     *             obj.wait(timeout, nanos);
-     *         ... // 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.
-     *
-     * @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) {
@@ -475,48 +463,6 @@
     }
 
     /**
-     * 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.
      * A subclass overrides the {@code finalize} method to dispose of