< prev index next >

src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java

Print this page




  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/publicdomain/zero/1.0/
  34  */
  35 
  36 package java.util.concurrent.locks;
  37 
  38 import java.util.Collection;
  39 import java.util.concurrent.TimeUnit;


  40 import jdk.internal.vm.annotation.ReservedStackAccess;
  41 
  42 /**
  43  * A reentrant mutual exclusion {@link Lock} with the same basic
  44  * behavior and semantics as the implicit monitor lock accessed using
  45  * {@code synchronized} methods and statements, but with extended
  46  * capabilities.
  47  *
  48  * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
  49  * successfully locking, but not yet unlocking it. A thread invoking
  50  * {@code lock} will return, successfully acquiring the lock, when
  51  * the lock is not owned by another thread. The method will return
  52  * immediately if the current thread already owns the lock. This can
  53  * be checked using methods {@link #isHeldByCurrentThread}, and {@link
  54  * #getHoldCount}.
  55  *
  56  * <p>The constructor for this class accepts an optional
  57  * <em>fairness</em> parameter.  When set {@code true}, under
  58  * contention, locks favor granting access to the longest-waiting
  59  * thread.  Otherwise this lock does not guarantee any particular


 107  */
 108 public class ReentrantLock implements Lock, java.io.Serializable {
 109     private static final long serialVersionUID = 7373984872572414699L;
 110     /** Synchronizer providing all implementation mechanics */
 111     private final Sync sync;
 112 
 113     /**
 114      * Base of synchronization control for this lock. Subclassed
 115      * into fair and nonfair versions below. Uses AQS state to
 116      * represent the number of holds on the lock.
 117      */
 118     abstract static class Sync extends AbstractQueuedSynchronizer {
 119         private static final long serialVersionUID = -5179523762034025860L;
 120 
 121         /**
 122          * Performs non-fair tryLock.  tryAcquire is implemented in
 123          * subclasses, but both need nonfair try for trylock method.
 124          */
 125         @ReservedStackAccess
 126         final boolean nonfairTryAcquire(int acquires) {
 127             final Thread current = Thread.currentThread();
 128             int c = getState();
 129             if (c == 0) {
 130                 if (compareAndSetState(0, acquires)) {
 131                     setExclusiveOwnerThread(current);
 132                     return true;
 133                 }
 134             }
 135             else if (current == getExclusiveOwnerThread()) {
 136                 int nextc = c + acquires;
 137                 if (nextc < 0) // overflow
 138                     throw new Error("Maximum lock count exceeded");
 139                 setState(nextc);
 140                 return true;
 141             }
 142             return false;
 143         }
 144 
 145         @ReservedStackAccess
 146         protected final boolean tryRelease(int releases) {
 147             int c = getState() - releases;
 148             if (Thread.currentThread() != getExclusiveOwnerThread())
 149                 throw new IllegalMonitorStateException();
 150             boolean free = false;
 151             if (c == 0) {
 152                 free = true;
 153                 setExclusiveOwnerThread(null);
 154             }
 155             setState(c);
 156             return free;
 157         }
 158 
 159         protected final boolean isHeldExclusively() {
 160             // While we must in general read state before owner,
 161             // we don't need to do so to check if current thread is owner
 162             return getExclusiveOwnerThread() == Thread.currentThread();
 163         }
 164 
 165         final ConditionObject newCondition() {
 166             return new ConditionObject();
 167         }
 168 
 169         // Methods relayed from outer class
 170 
 171         final Thread getOwner() {
 172             return getState() == 0 ? null : getExclusiveOwnerThread();
 173         }
 174 
 175         final int getHoldCount() {
 176             return isHeldExclusively() ? getState() : 0;
 177         }
 178 
 179         final boolean isLocked() {
 180             return getState() != 0;
 181         }
 182 
 183         /**
 184          * Reconstitutes the instance from a stream (that is, deserializes it).
 185          */
 186         private void readObject(java.io.ObjectInputStream s)
 187             throws java.io.IOException, ClassNotFoundException {
 188             s.defaultReadObject();
 189             setState(0); // reset to unlocked state
 190         }
 191     }
 192 


 194      * Sync object for non-fair locks
 195      */
 196     static final class NonfairSync extends Sync {
 197         private static final long serialVersionUID = 7316153563782823691L;
 198         protected final boolean tryAcquire(int acquires) {
 199             return nonfairTryAcquire(acquires);
 200         }
 201     }
 202 
 203     /**
 204      * Sync object for fair locks
 205      */
 206     static final class FairSync extends Sync {
 207         private static final long serialVersionUID = -3000897897090466540L;
 208         /**
 209          * Fair version of tryAcquire.  Don't grant access unless
 210          * recursive call or no waiters or is first.
 211          */
 212         @ReservedStackAccess
 213         protected final boolean tryAcquire(int acquires) {
 214             final Thread current = Thread.currentThread();
 215             int c = getState();
 216             if (c == 0) {
 217                 if (!hasQueuedPredecessors() &&
 218                     compareAndSetState(0, acquires)) {
 219                     setExclusiveOwnerThread(current);
 220                     return true;
 221                 }
 222             }
 223             else if (current == getExclusiveOwnerThread()) {
 224                 int nextc = c + acquires;
 225                 if (nextc < 0)
 226                     throw new Error("Maximum lock count exceeded");
 227                 setState(nextc);
 228                 return true;
 229             }
 230             return false;
 231         }
 232     }
 233 
 234     /**
 235      * Creates an instance of {@code ReentrantLock}.
 236      * This is equivalent to using {@code ReentrantLock(false)}.
 237      */
 238     public ReentrantLock() {
 239         sync = new NonfairSync();
 240     }
 241 
 242     /**
 243      * Creates an instance of {@code ReentrantLock} with the


 576      * Returns {@code true} if this lock has fairness set true.
 577      *
 578      * @return {@code true} if this lock has fairness set true
 579      */
 580     public final boolean isFair() {
 581         return sync instanceof FairSync;
 582     }
 583 
 584     /**
 585      * Returns the thread that currently owns this lock, or
 586      * {@code null} if not owned. When this method is called by a
 587      * thread that is not the owner, the return value reflects a
 588      * best-effort approximation of current lock status. For example,
 589      * the owner may be momentarily {@code null} even if there are
 590      * threads trying to acquire the lock but have not yet done so.
 591      * This method is designed to facilitate construction of
 592      * subclasses that provide more extensive lock monitoring
 593      * facilities.
 594      *
 595      * @return the owner, or {@code null} if not owned

 596      */
 597     protected Thread getOwner() {
 598         return sync.getOwner();
 599     }
 600 
 601     /**
 602      * Queries whether any threads are waiting to acquire this lock. Note that
 603      * because cancellations may occur at any time, a {@code true}
 604      * return does not guarantee that any other thread will ever
 605      * acquire this lock.  This method is designed primarily for use in
 606      * monitoring of the system state.
 607      *
 608      * @return {@code true} if there may be other threads waiting to
 609      *         acquire the lock
 610      */
 611     public final boolean hasQueuedThreads() {
 612         return sync.hasQueuedThreads();
 613     }
 614 
 615     /**
 616      * Queries whether the given thread is waiting to acquire this
 617      * lock. Note that because cancellations may occur at any time, a
 618      * {@code true} return does not guarantee that this thread


 718      *         not associated with this lock
 719      * @throws NullPointerException if the condition is null
 720      */
 721     protected Collection<Thread> getWaitingThreads(Condition condition) {
 722         if (condition == null)
 723             throw new NullPointerException();
 724         if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
 725             throw new IllegalArgumentException("not owner");
 726         return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
 727     }
 728 
 729     /**
 730      * Returns a string identifying this lock, as well as its lock state.
 731      * The state, in brackets, includes either the String {@code "Unlocked"}
 732      * or the String {@code "Locked by"} followed by the
 733      * {@linkplain Thread#getName name} of the owning thread.
 734      *
 735      * @return a string identifying this lock, as well as its lock state
 736      */
 737     public String toString() {
 738         Thread o = sync.getOwner();






 739         return super.toString() + ((o == null) ?
 740                                    "[Unlocked]" :
 741                                    "[Locked by thread " + o.getName() + "]");
 742     }
 743 }


  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/publicdomain/zero/1.0/
  34  */
  35 
  36 package java.util.concurrent.locks;
  37 
  38 import java.util.Collection;
  39 import java.util.concurrent.TimeUnit;
  40 
  41 import jdk.internal.misc.Strands;
  42 import jdk.internal.vm.annotation.ReservedStackAccess;
  43 
  44 /**
  45  * A reentrant mutual exclusion {@link Lock} with the same basic
  46  * behavior and semantics as the implicit monitor lock accessed using
  47  * {@code synchronized} methods and statements, but with extended
  48  * capabilities.
  49  *
  50  * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
  51  * successfully locking, but not yet unlocking it. A thread invoking
  52  * {@code lock} will return, successfully acquiring the lock, when
  53  * the lock is not owned by another thread. The method will return
  54  * immediately if the current thread already owns the lock. This can
  55  * be checked using methods {@link #isHeldByCurrentThread}, and {@link
  56  * #getHoldCount}.
  57  *
  58  * <p>The constructor for this class accepts an optional
  59  * <em>fairness</em> parameter.  When set {@code true}, under
  60  * contention, locks favor granting access to the longest-waiting
  61  * thread.  Otherwise this lock does not guarantee any particular


 109  */
 110 public class ReentrantLock implements Lock, java.io.Serializable {
 111     private static final long serialVersionUID = 7373984872572414699L;
 112     /** Synchronizer providing all implementation mechanics */
 113     private final Sync sync;
 114 
 115     /**
 116      * Base of synchronization control for this lock. Subclassed
 117      * into fair and nonfair versions below. Uses AQS state to
 118      * represent the number of holds on the lock.
 119      */
 120     abstract static class Sync extends AbstractQueuedSynchronizer {
 121         private static final long serialVersionUID = -5179523762034025860L;
 122 
 123         /**
 124          * Performs non-fair tryLock.  tryAcquire is implemented in
 125          * subclasses, but both need nonfair try for trylock method.
 126          */
 127         @ReservedStackAccess
 128         final boolean nonfairTryAcquire(int acquires) {
 129             final Object current = Strands.currentStrand();
 130             int c = getState();
 131             if (c == 0) {
 132                 if (compareAndSetState(0, acquires)) {
 133                     setExclusiveOwner(current);
 134                     return true;
 135                 }
 136             }
 137             else if (current == getExclusiveOwner()) {
 138                 int nextc = c + acquires;
 139                 if (nextc < 0) // overflow
 140                     throw new Error("Maximum lock count esetExclusiveOwnexceeded");
 141                 setState(nextc);
 142                 return true;
 143             }
 144             return false;
 145         }
 146 
 147         @ReservedStackAccess
 148         protected final boolean tryRelease(int releases) {
 149             int c = getState() - releases;
 150             if (Strands.currentStrand() != getExclusiveOwner())
 151                 throw new IllegalMonitorStateException();
 152             boolean free = false;
 153             if (c == 0) {
 154                 free = true;
 155                 setExclusiveOwner(null);
 156             }
 157             setState(c);
 158             return free;
 159         }
 160 
 161         protected final boolean isHeldExclusively() {
 162             // While we must in general read state before owner,
 163             // we don't need to do so to check if current thread is owner
 164             return getExclusiveOwner() == Strands.currentStrand();
 165         }
 166 
 167         final ConditionObject newCondition() {
 168             return new ConditionObject();
 169         }
 170 
 171         // Methods relayed from outer class
 172 
 173         final Object getOwner() {
 174             return getState() == 0 ? null : getExclusiveOwner();
 175         }
 176 
 177         final int getHoldCount() {
 178             return isHeldExclusively() ? getState() : 0;
 179         }
 180 
 181         final boolean isLocked() {
 182             return getState() != 0;
 183         }
 184 
 185         /**
 186          * Reconstitutes the instance from a stream (that is, deserializes it).
 187          */
 188         private void readObject(java.io.ObjectInputStream s)
 189             throws java.io.IOException, ClassNotFoundException {
 190             s.defaultReadObject();
 191             setState(0); // reset to unlocked state
 192         }
 193     }
 194 


 196      * Sync object for non-fair locks
 197      */
 198     static final class NonfairSync extends Sync {
 199         private static final long serialVersionUID = 7316153563782823691L;
 200         protected final boolean tryAcquire(int acquires) {
 201             return nonfairTryAcquire(acquires);
 202         }
 203     }
 204 
 205     /**
 206      * Sync object for fair locks
 207      */
 208     static final class FairSync extends Sync {
 209         private static final long serialVersionUID = -3000897897090466540L;
 210         /**
 211          * Fair version of tryAcquire.  Don't grant access unless
 212          * recursive call or no waiters or is first.
 213          */
 214         @ReservedStackAccess
 215         protected final boolean tryAcquire(int acquires) {
 216             final Object current = Strands.currentStrand();
 217             int c = getState();
 218             if (c == 0) {
 219                 if (!hasQueuedPredecessors() &&
 220                     compareAndSetState(0, acquires)) {
 221                     setExclusiveOwner(current);
 222                     return true;
 223                 }
 224             }
 225             else if (current == getExclusiveOwner()) {
 226                 int nextc = c + acquires;
 227                 if (nextc < 0)
 228                     throw new Error("Maximum lock count exceeded");
 229                 setState(nextc);
 230                 return true;
 231             }
 232             return false;
 233         }
 234     }
 235 
 236     /**
 237      * Creates an instance of {@code ReentrantLock}.
 238      * This is equivalent to using {@code ReentrantLock(false)}.
 239      */
 240     public ReentrantLock() {
 241         sync = new NonfairSync();
 242     }
 243 
 244     /**
 245      * Creates an instance of {@code ReentrantLock} with the


 578      * Returns {@code true} if this lock has fairness set true.
 579      *
 580      * @return {@code true} if this lock has fairness set true
 581      */
 582     public final boolean isFair() {
 583         return sync instanceof FairSync;
 584     }
 585 
 586     /**
 587      * Returns the thread that currently owns this lock, or
 588      * {@code null} if not owned. When this method is called by a
 589      * thread that is not the owner, the return value reflects a
 590      * best-effort approximation of current lock status. For example,
 591      * the owner may be momentarily {@code null} even if there are
 592      * threads trying to acquire the lock but have not yet done so.
 593      * This method is designed to facilitate construction of
 594      * subclasses that provide more extensive lock monitoring
 595      * facilities.
 596      *
 597      * @return the owner, or {@code null} if not owned
 598      * @throws ClassCastException if owned by a fiber
 599      */
 600     protected Thread getOwner() {
 601         return (Thread) sync.getOwner();
 602     }
 603 
 604     /**
 605      * Queries whether any threads are waiting to acquire this lock. Note that
 606      * because cancellations may occur at any time, a {@code true}
 607      * return does not guarantee that any other thread will ever
 608      * acquire this lock.  This method is designed primarily for use in
 609      * monitoring of the system state.
 610      *
 611      * @return {@code true} if there may be other threads waiting to
 612      *         acquire the lock
 613      */
 614     public final boolean hasQueuedThreads() {
 615         return sync.hasQueuedThreads();
 616     }
 617 
 618     /**
 619      * Queries whether the given thread is waiting to acquire this
 620      * lock. Note that because cancellations may occur at any time, a
 621      * {@code true} return does not guarantee that this thread


 721      *         not associated with this lock
 722      * @throws NullPointerException if the condition is null
 723      */
 724     protected Collection<Thread> getWaitingThreads(Condition condition) {
 725         if (condition == null)
 726             throw new NullPointerException();
 727         if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
 728             throw new IllegalArgumentException("not owner");
 729         return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
 730     }
 731 
 732     /**
 733      * Returns a string identifying this lock, as well as its lock state.
 734      * The state, in brackets, includes either the String {@code "Unlocked"}
 735      * or the String {@code "Locked by"} followed by the
 736      * {@linkplain Thread#getName name} of the owning thread.
 737      *
 738      * @return a string identifying this lock, as well as its lock state
 739      */
 740     public String toString() {
 741         Object o = sync.getOwner();
 742         String name = "";
 743         if (o instanceof Thread) {
 744             name = "thread " + ((Thread) o).getName();
 745         } else if (o instanceof Fiber) {
 746             name = "Fiber";
 747         }
 748         return super.toString() + ((o == null) ?
 749                                    "[Unlocked]" :
 750                                    "[Locked by " + name + "]");
 751     }
 752 }
< prev index next >