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

Print this page




  99  * locks: a deserialized lock is in the unlocked state, regardless of
 100  * its state when serialized.
 101  *
 102  * <p>This lock supports a maximum of 2147483647 recursive locks by
 103  * the same thread. Attempts to exceed this limit result in
 104  * {@link Error} throws from locking methods.
 105  *
 106  * @since 1.5
 107  * @author Doug Lea
 108  */
 109 public class ReentrantLock implements Lock, java.io.Serializable {
 110     private static final long serialVersionUID = 7373984872572414699L;
 111     /** Synchronizer providing all implementation mechanics */
 112     private final Sync sync;
 113 
 114     /**
 115      * Base of synchronization control for this lock. Subclassed
 116      * into fair and nonfair versions below. Uses AQS state to
 117      * represent the number of holds on the lock.
 118      */
 119     static abstract class Sync extends AbstractQueuedSynchronizer {
 120         private static final long serialVersionUID = -5179523762034025860L;
 121 
 122         /**
 123          * Performs {@link Lock#lock}. The main reason for subclassing
 124          * is to allow fast path for nonfair version.
 125          */
 126         abstract void lock();
 127 
 128         /**
 129          * Performs non-fair tryLock.  tryAcquire is
 130          * implemented in subclasses, but both need nonfair
 131          * try for trylock method.
 132          */
 133         final boolean nonfairTryAcquire(int acquires) {
 134             final Thread current = Thread.currentThread();
 135             int c = getState();
 136             if (c == 0) {
 137                 if (compareAndSetState(0, acquires)) {
 138                     setExclusiveOwnerThread(current);
 139                     return true;


 183         }
 184 
 185         final boolean isLocked() {
 186             return getState() != 0;
 187         }
 188 
 189         /**
 190          * Reconstitutes this lock instance from a stream.
 191          * @param s the stream
 192          */
 193         private void readObject(java.io.ObjectInputStream s)
 194             throws java.io.IOException, ClassNotFoundException {
 195             s.defaultReadObject();
 196             setState(0); // reset to unlocked state
 197         }
 198     }
 199 
 200     /**
 201      * Sync object for non-fair locks
 202      */
 203     final static class NonfairSync extends Sync {
 204         private static final long serialVersionUID = 7316153563782823691L;
 205 
 206         /**
 207          * Performs lock.  Try immediate barge, backing up to normal
 208          * acquire on failure.
 209          */
 210         final void lock() {
 211             if (compareAndSetState(0, 1))
 212                 setExclusiveOwnerThread(Thread.currentThread());
 213             else
 214                 acquire(1);
 215         }
 216 
 217         protected final boolean tryAcquire(int acquires) {
 218             return nonfairTryAcquire(acquires);
 219         }
 220     }
 221 
 222     /**
 223      * Sync object for fair locks
 224      */
 225     final static class FairSync extends Sync {
 226         private static final long serialVersionUID = -3000897897090466540L;
 227 
 228         final void lock() {
 229             acquire(1);
 230         }
 231 
 232         /**
 233          * Fair version of tryAcquire.  Don't grant access unless
 234          * recursive call or no waiters or is first.
 235          */
 236         protected final boolean tryAcquire(int acquires) {
 237             final Thread current = Thread.currentThread();
 238             int c = getState();
 239             if (c == 0) {
 240                 if (!hasQueuedPredecessors() &&
 241                     compareAndSetState(0, acquires)) {
 242                     setExclusiveOwnerThread(current);
 243                     return true;
 244                 }
 245             }


 252             }
 253             return false;
 254         }
 255     }
 256 
 257     /**
 258      * Creates an instance of {@code ReentrantLock}.
 259      * This is equivalent to using {@code ReentrantLock(false)}.
 260      */
 261     public ReentrantLock() {
 262         sync = new NonfairSync();
 263     }
 264 
 265     /**
 266      * Creates an instance of {@code ReentrantLock} with the
 267      * given fairness policy.
 268      *
 269      * @param fair {@code true} if this lock should use a fair ordering policy
 270      */
 271     public ReentrantLock(boolean fair) {
 272         sync = (fair)? new FairSync() : new NonfairSync();
 273     }
 274 
 275     /**
 276      * Acquires the lock.
 277      *
 278      * <p>Acquires the lock if it is not held by another thread and returns
 279      * immediately, setting the lock hold count to one.
 280      *
 281      * <p>If the current thread already holds the lock then the hold
 282      * count is incremented by one and the method returns immediately.
 283      *
 284      * <p>If the lock is held by another thread then the
 285      * current thread becomes disabled for thread scheduling
 286      * purposes and lies dormant until the lock has been acquired,
 287      * at which time the lock hold count is set to one.
 288      */
 289     public void lock() {
 290         sync.lock();
 291     }
 292 


 423      *
 424      * <p>If the specified waiting time elapses then the value {@code false}
 425      * is returned.  If the time is less than or equal to zero, the method
 426      * will not wait at all.
 427      *
 428      * <p>In this implementation, as this method is an explicit
 429      * interruption point, preference is given to responding to the
 430      * interrupt over normal or reentrant acquisition of the lock, and
 431      * over reporting the elapse of the waiting time.
 432      *
 433      * @param timeout the time to wait for the lock
 434      * @param unit the time unit of the timeout argument
 435      * @return {@code true} if the lock was free and was acquired by the
 436      *         current thread, or the lock was already held by the current
 437      *         thread; and {@code false} if the waiting time elapsed before
 438      *         the lock could be acquired
 439      * @throws InterruptedException if the current thread is interrupted
 440      * @throws NullPointerException if the time unit is null
 441      *
 442      */
 443     public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {

 444         return sync.tryAcquireNanos(1, unit.toNanos(timeout));
 445     }
 446 
 447     /**
 448      * Attempts to release this lock.
 449      *
 450      * <p>If the current thread is the holder of this lock then the hold
 451      * count is decremented.  If the hold count is now zero then the lock
 452      * is released.  If the current thread is not the holder of this
 453      * lock then {@link IllegalMonitorStateException} is thrown.
 454      *
 455      * @throws IllegalMonitorStateException if the current thread does not
 456      *         hold this lock
 457      */
 458     public void unlock() {
 459         sync.release(1);
 460     }
 461 
 462     /**
 463      * Returns a {@link Condition} instance for use with this




  99  * locks: a deserialized lock is in the unlocked state, regardless of
 100  * its state when serialized.
 101  *
 102  * <p>This lock supports a maximum of 2147483647 recursive locks by
 103  * the same thread. Attempts to exceed this limit result in
 104  * {@link Error} throws from locking methods.
 105  *
 106  * @since 1.5
 107  * @author Doug Lea
 108  */
 109 public class ReentrantLock implements Lock, java.io.Serializable {
 110     private static final long serialVersionUID = 7373984872572414699L;
 111     /** Synchronizer providing all implementation mechanics */
 112     private final Sync sync;
 113 
 114     /**
 115      * Base of synchronization control for this lock. Subclassed
 116      * into fair and nonfair versions below. Uses AQS state to
 117      * represent the number of holds on the lock.
 118      */
 119     abstract static class Sync extends AbstractQueuedSynchronizer {
 120         private static final long serialVersionUID = -5179523762034025860L;
 121 
 122         /**
 123          * Performs {@link Lock#lock}. The main reason for subclassing
 124          * is to allow fast path for nonfair version.
 125          */
 126         abstract void lock();
 127 
 128         /**
 129          * Performs non-fair tryLock.  tryAcquire is
 130          * implemented in subclasses, but both need nonfair
 131          * try for trylock method.
 132          */
 133         final boolean nonfairTryAcquire(int acquires) {
 134             final Thread current = Thread.currentThread();
 135             int c = getState();
 136             if (c == 0) {
 137                 if (compareAndSetState(0, acquires)) {
 138                     setExclusiveOwnerThread(current);
 139                     return true;


 183         }
 184 
 185         final boolean isLocked() {
 186             return getState() != 0;
 187         }
 188 
 189         /**
 190          * Reconstitutes this lock instance from a stream.
 191          * @param s the stream
 192          */
 193         private void readObject(java.io.ObjectInputStream s)
 194             throws java.io.IOException, ClassNotFoundException {
 195             s.defaultReadObject();
 196             setState(0); // reset to unlocked state
 197         }
 198     }
 199 
 200     /**
 201      * Sync object for non-fair locks
 202      */
 203     static final class NonfairSync extends Sync {
 204         private static final long serialVersionUID = 7316153563782823691L;
 205 
 206         /**
 207          * Performs lock.  Try immediate barge, backing up to normal
 208          * acquire on failure.
 209          */
 210         final void lock() {
 211             if (compareAndSetState(0, 1))
 212                 setExclusiveOwnerThread(Thread.currentThread());
 213             else
 214                 acquire(1);
 215         }
 216 
 217         protected final boolean tryAcquire(int acquires) {
 218             return nonfairTryAcquire(acquires);
 219         }
 220     }
 221 
 222     /**
 223      * Sync object for fair locks
 224      */
 225     static final class FairSync extends Sync {
 226         private static final long serialVersionUID = -3000897897090466540L;
 227 
 228         final void lock() {
 229             acquire(1);
 230         }
 231 
 232         /**
 233          * Fair version of tryAcquire.  Don't grant access unless
 234          * recursive call or no waiters or is first.
 235          */
 236         protected final boolean tryAcquire(int acquires) {
 237             final Thread current = Thread.currentThread();
 238             int c = getState();
 239             if (c == 0) {
 240                 if (!hasQueuedPredecessors() &&
 241                     compareAndSetState(0, acquires)) {
 242                     setExclusiveOwnerThread(current);
 243                     return true;
 244                 }
 245             }


 252             }
 253             return false;
 254         }
 255     }
 256 
 257     /**
 258      * Creates an instance of {@code ReentrantLock}.
 259      * This is equivalent to using {@code ReentrantLock(false)}.
 260      */
 261     public ReentrantLock() {
 262         sync = new NonfairSync();
 263     }
 264 
 265     /**
 266      * Creates an instance of {@code ReentrantLock} with the
 267      * given fairness policy.
 268      *
 269      * @param fair {@code true} if this lock should use a fair ordering policy
 270      */
 271     public ReentrantLock(boolean fair) {
 272         sync = fair ? new FairSync() : new NonfairSync();
 273     }
 274 
 275     /**
 276      * Acquires the lock.
 277      *
 278      * <p>Acquires the lock if it is not held by another thread and returns
 279      * immediately, setting the lock hold count to one.
 280      *
 281      * <p>If the current thread already holds the lock then the hold
 282      * count is incremented by one and the method returns immediately.
 283      *
 284      * <p>If the lock is held by another thread then the
 285      * current thread becomes disabled for thread scheduling
 286      * purposes and lies dormant until the lock has been acquired,
 287      * at which time the lock hold count is set to one.
 288      */
 289     public void lock() {
 290         sync.lock();
 291     }
 292 


 423      *
 424      * <p>If the specified waiting time elapses then the value {@code false}
 425      * is returned.  If the time is less than or equal to zero, the method
 426      * will not wait at all.
 427      *
 428      * <p>In this implementation, as this method is an explicit
 429      * interruption point, preference is given to responding to the
 430      * interrupt over normal or reentrant acquisition of the lock, and
 431      * over reporting the elapse of the waiting time.
 432      *
 433      * @param timeout the time to wait for the lock
 434      * @param unit the time unit of the timeout argument
 435      * @return {@code true} if the lock was free and was acquired by the
 436      *         current thread, or the lock was already held by the current
 437      *         thread; and {@code false} if the waiting time elapsed before
 438      *         the lock could be acquired
 439      * @throws InterruptedException if the current thread is interrupted
 440      * @throws NullPointerException if the time unit is null
 441      *
 442      */
 443     public boolean tryLock(long timeout, TimeUnit unit)
 444             throws InterruptedException {
 445         return sync.tryAcquireNanos(1, unit.toNanos(timeout));
 446     }
 447 
 448     /**
 449      * Attempts to release this lock.
 450      *
 451      * <p>If the current thread is the holder of this lock then the hold
 452      * count is decremented.  If the hold count is now zero then the lock
 453      * is released.  If the current thread is not the holder of this
 454      * lock then {@link IllegalMonitorStateException} is thrown.
 455      *
 456      * @throws IllegalMonitorStateException if the current thread does not
 457      *         hold this lock
 458      */
 459     public void unlock() {
 460         sync.release(1);
 461     }
 462 
 463     /**
 464      * Returns a {@link Condition} instance for use with this