src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
changeset 47302 f517fa4f4dc6
parent 47216 71c04702a3d5
child 48046 98801bd22f5b
--- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Tue Oct 03 13:32:04 2017 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Tue Oct 03 13:37:01 2017 -0700
@@ -194,19 +194,13 @@
  * represent the locked state. While a non-reentrant lock
  * does not strictly require recording of the current owner
  * thread, this class does so anyway to make usage easier to monitor.
- * It also supports conditions and exposes
- * one of the instrumentation methods:
+ * It also supports conditions and exposes some instrumentation methods:
  *
  * <pre> {@code
  * class Mutex implements Lock, java.io.Serializable {
  *
  *   // Our internal helper class
  *   private static class Sync extends AbstractQueuedSynchronizer {
- *     // Reports whether in locked state
- *     protected boolean isHeldExclusively() {
- *       return getState() == 1;
- *     }
- *
  *     // Acquires the lock if state is zero
  *     public boolean tryAcquire(int acquires) {
  *       assert acquires == 1; // Otherwise unused
@@ -220,14 +214,27 @@
  *     // Releases the lock by setting state to zero
  *     protected boolean tryRelease(int releases) {
  *       assert releases == 1; // Otherwise unused
- *       if (getState() == 0) throw new IllegalMonitorStateException();
+ *       if (!isHeldExclusively())
+ *         throw new IllegalMonitorStateException();
  *       setExclusiveOwnerThread(null);
  *       setState(0);
  *       return true;
  *     }
  *
+ *     // Reports whether in locked state
+ *     public boolean isLocked() {
+ *       return getState() != 0;
+ *     }
+ *
+ *     public boolean isHeldExclusively() {
+ *       // a data race, but safe due to out-of-thin-air guarantees
+ *       return getExclusiveOwnerThread() == Thread.currentThread();
+ *     }
+ *
  *     // Provides a Condition
- *     Condition newCondition() { return new ConditionObject(); }
+ *     public Condition newCondition() {
+ *       return new ConditionObject();
+ *     }
  *
  *     // Deserializes properly
  *     private void readObject(ObjectInputStream s)
@@ -240,12 +247,17 @@
  *   // The sync object does all the hard work. We just forward to it.
  *   private final Sync sync = new Sync();
  *
- *   public void lock()                { sync.acquire(1); }
- *   public boolean tryLock()          { return sync.tryAcquire(1); }
- *   public void unlock()              { sync.release(1); }
- *   public Condition newCondition()   { return sync.newCondition(); }
- *   public boolean isLocked()         { return sync.isHeldExclusively(); }
- *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+ *   public void lock()              { sync.acquire(1); }
+ *   public boolean tryLock()        { return sync.tryAcquire(1); }
+ *   public void unlock()            { sync.release(1); }
+ *   public Condition newCondition() { return sync.newCondition(); }
+ *   public boolean isLocked()       { return sync.isLocked(); }
+ *   public boolean isHeldByCurrentThread() {
+ *     return sync.isHeldExclusively();
+ *   }
+ *   public boolean hasQueuedThreads() {
+ *     return sync.hasQueuedThreads();
+ *   }
  *   public void lockInterruptibly() throws InterruptedException {
  *     sync.acquireInterruptibly(1);
  *   }
@@ -1193,8 +1205,7 @@
     /**
      * Returns {@code true} if synchronization is held exclusively with
      * respect to the current (calling) thread.  This method is invoked
-     * upon each call to a non-waiting {@link ConditionObject} method.
-     * (Waiting methods instead invoke {@link #release}.)
+     * upon each call to a {@link ConditionObject} method.
      *
      * <p>The default implementation throws {@link
      * UnsupportedOperationException}. This method is invoked
@@ -1834,9 +1845,8 @@
     }
 
     /**
-     * Condition implementation for a {@link
-     * AbstractQueuedSynchronizer} serving as the basis of a {@link
-     * Lock} implementation.
+     * Condition implementation for a {@link AbstractQueuedSynchronizer}
+     * serving as the basis of a {@link Lock} implementation.
      *
      * <p>Method documentation for this class describes mechanics,
      * not behavioral specifications from the point of view of Lock
@@ -1867,6 +1877,8 @@
          * @return its new wait node
          */
         private Node addConditionWaiter() {
+            if (!isHeldExclusively())
+                throw new IllegalMonitorStateException();
             Node t = lastWaiter;
             // If lastWaiter is cancelled, clean out.
             if (t != null && t.waitStatus != Node.CONDITION) {