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

Print this page




 198  *        try { return m.put(key, value); }
 199  *        finally { w.unlock(); }
 200  *    }
 201  *    public void clear() {
 202  *        w.lock();
 203  *        try { m.clear(); }
 204  *        finally { w.unlock(); }
 205  *    }
 206  * }}</pre>
 207  *
 208  * <h3>Implementation Notes</h3>
 209  *
 210  * <p>This lock supports a maximum of 65535 recursive write locks
 211  * and 65535 read locks. Attempts to exceed these limits result in
 212  * {@link Error} throws from locking methods.
 213  *
 214  * @since 1.5
 215  * @author Doug Lea
 216  *
 217  */
 218 public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable  {

 219     private static final long serialVersionUID = -6992448646407690164L;
 220     /** Inner class providing readlock */
 221     private final ReentrantReadWriteLock.ReadLock readerLock;
 222     /** Inner class providing writelock */
 223     private final ReentrantReadWriteLock.WriteLock writerLock;
 224     /** Performs all synchronization mechanics */
 225     final Sync sync;
 226 
 227     /**
 228      * Creates a new {@code ReentrantReadWriteLock} with
 229      * default (nonfair) ordering properties.
 230      */
 231     public ReentrantReadWriteLock() {
 232         this(false);
 233     }
 234 
 235     /**
 236      * Creates a new {@code ReentrantReadWriteLock} with
 237      * the given fairness policy.
 238      *
 239      * @param fair {@code true} if this lock should use a fair ordering policy
 240      */
 241     public ReentrantReadWriteLock(boolean fair) {
 242         sync = fair ? new FairSync() : new NonfairSync();
 243         readerLock = new ReadLock(this);
 244         writerLock = new WriteLock(this);
 245     }
 246 
 247     public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
 248     public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
 249 
 250     /**
 251      * Synchronization implementation for ReentrantReadWriteLock.
 252      * Subclassed into fair and nonfair versions.
 253      */
 254     static abstract class Sync extends AbstractQueuedSynchronizer {
 255         private static final long serialVersionUID = 6317671515068378041L;
 256 
 257         /*
 258          * Read vs write count extraction constants and functions.
 259          * Lock state is logically divided into two unsigned shorts:
 260          * The lower one representing the exclusive (writer) lock hold count,
 261          * and the upper the shared (reader) hold count.
 262          */
 263 
 264         static final int SHARED_SHIFT   = 16;
 265         static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
 266         static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
 267         static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
 268 
 269         /** Returns the number of shared holds represented in count  */
 270         static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
 271         /** Returns the number of exclusive holds represented in count  */
 272         static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
 273 
 274         /**


 601                     }
 602                     return true;
 603                 }
 604             }
 605         }
 606 
 607         protected final boolean isHeldExclusively() {
 608             // While we must in general read state before owner,
 609             // we don't need to do so to check if current thread is owner
 610             return getExclusiveOwnerThread() == Thread.currentThread();
 611         }
 612 
 613         // Methods relayed to outer class
 614 
 615         final ConditionObject newCondition() {
 616             return new ConditionObject();
 617         }
 618 
 619         final Thread getOwner() {
 620             // Must read state before owner to ensure memory consistency
 621             return ((exclusiveCount(getState()) == 0)?
 622                     null :
 623                     getExclusiveOwnerThread());
 624         }
 625 
 626         final int getReadLockCount() {
 627             return sharedCount(getState());
 628         }
 629 
 630         final boolean isWriteLocked() {
 631             return exclusiveCount(getState()) != 0;
 632         }
 633 
 634         final int getWriteHoldCount() {
 635             return isHeldExclusively() ? exclusiveCount(getState()) : 0;
 636         }
 637 
 638         final int getReadHoldCount() {
 639             if (getReadLockCount() == 0)
 640                 return 0;
 641 


 652             return count;
 653         }
 654 
 655         /**
 656          * Reconstitute this lock instance from a stream
 657          * @param s the stream
 658          */
 659         private void readObject(java.io.ObjectInputStream s)
 660             throws java.io.IOException, ClassNotFoundException {
 661             s.defaultReadObject();
 662             readHolds = new ThreadLocalHoldCounter();
 663             setState(0); // reset to unlocked state
 664         }
 665 
 666         final int getCount() { return getState(); }
 667     }
 668 
 669     /**
 670      * Nonfair version of Sync
 671      */
 672     final static class NonfairSync extends Sync {
 673         private static final long serialVersionUID = -8159625535654395037L;
 674         final boolean writerShouldBlock() {
 675             return false; // writers can always barge
 676         }
 677         final boolean readerShouldBlock() {
 678             /* As a heuristic to avoid indefinite writer starvation,
 679              * block if the thread that momentarily appears to be head
 680              * of queue, if one exists, is a waiting writer.  This is
 681              * only a probabilistic effect since a new reader will not
 682              * block if there is a waiting writer behind other enabled
 683              * readers that have not yet drained from the queue.
 684              */
 685             return apparentlyFirstQueuedIsExclusive();
 686         }
 687     }
 688 
 689     /**
 690      * Fair version of Sync
 691      */
 692     final static class FairSync extends Sync {
 693         private static final long serialVersionUID = -2274990926593161451L;
 694         final boolean writerShouldBlock() {
 695             return hasQueuedPredecessors();
 696         }
 697         final boolean readerShouldBlock() {
 698             return hasQueuedPredecessors();
 699         }
 700     }
 701 
 702     /**
 703      * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
 704      */
 705     public static class ReadLock implements Lock, java.io.Serializable  {
 706         private static final long serialVersionUID = -5992448646407690164L;
 707         private final Sync sync;
 708 
 709         /**
 710          * Constructor for use by subclasses
 711          *
 712          * @param lock the outer lock object


 850          *
 851          * </ul> then {@link InterruptedException} is thrown and the
 852          * current thread's interrupted status is cleared.
 853          *
 854          * <p>If the specified waiting time elapses then the value
 855          * {@code false} is returned.  If the time is less than or
 856          * equal to zero, the method will not wait at all.
 857          *
 858          * <p>In this implementation, as this method is an explicit
 859          * interruption point, preference is given to responding to
 860          * the interrupt over normal or reentrant acquisition of the
 861          * lock, and over reporting the elapse of the waiting time.
 862          *
 863          * @param timeout the time to wait for the read lock
 864          * @param unit the time unit of the timeout argument
 865          * @return {@code true} if the read lock was acquired
 866          * @throws InterruptedException if the current thread is interrupted
 867          * @throws NullPointerException if the time unit is null
 868          *
 869          */
 870         public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {

 871             return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
 872         }
 873 
 874         /**
 875          * Attempts to release this lock.
 876          *
 877          * <p> If the number of readers is now zero then the lock
 878          * is made available for write lock attempts.
 879          */
 880         public  void unlock() {
 881             sync.releaseShared(1);
 882         }
 883 
 884         /**
 885          * Throws {@code UnsupportedOperationException} because
 886          * {@code ReadLocks} do not support conditions.
 887          *
 888          * @throws UnsupportedOperationException always
 889          */
 890         public Condition newCondition() {


1091          * {@code false} is returned.  If the time is less than or
1092          * equal to zero, the method will not wait at all.
1093          *
1094          * <p>In this implementation, as this method is an explicit
1095          * interruption point, preference is given to responding to
1096          * the interrupt over normal or reentrant acquisition of the
1097          * lock, and over reporting the elapse of the waiting time.
1098          *
1099          * @param timeout the time to wait for the write lock
1100          * @param unit the time unit of the timeout argument
1101          *
1102          * @return {@code true} if the lock was free and was acquired
1103          * by the current thread, or the write lock was already held by the
1104          * current thread; and {@code false} if the waiting time
1105          * elapsed before the lock could be acquired.
1106          *
1107          * @throws InterruptedException if the current thread is interrupted
1108          * @throws NullPointerException if the time unit is null
1109          *
1110          */
1111         public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {

1112             return sync.tryAcquireNanos(1, unit.toNanos(timeout));
1113         }
1114 
1115         /**
1116          * Attempts to release this lock.
1117          *
1118          * <p>If the current thread is the holder of this lock then
1119          * the hold count is decremented. If the hold count is now
1120          * zero then the lock is released.  If the current thread is
1121          * not the holder of this lock then {@link
1122          * IllegalMonitorStateException} is thrown.
1123          *
1124          * @throws IllegalMonitorStateException if the current thread does not
1125          * hold this lock.
1126          */
1127         public void unlock() {
1128             sync.release(1);
1129         }
1130 
1131         /**




 198  *        try { return m.put(key, value); }
 199  *        finally { w.unlock(); }
 200  *    }
 201  *    public void clear() {
 202  *        w.lock();
 203  *        try { m.clear(); }
 204  *        finally { w.unlock(); }
 205  *    }
 206  * }}</pre>
 207  *
 208  * <h3>Implementation Notes</h3>
 209  *
 210  * <p>This lock supports a maximum of 65535 recursive write locks
 211  * and 65535 read locks. Attempts to exceed these limits result in
 212  * {@link Error} throws from locking methods.
 213  *
 214  * @since 1.5
 215  * @author Doug Lea
 216  *
 217  */
 218 public class ReentrantReadWriteLock
 219         implements ReadWriteLock, java.io.Serializable {
 220     private static final long serialVersionUID = -6992448646407690164L;
 221     /** Inner class providing readlock */
 222     private final ReentrantReadWriteLock.ReadLock readerLock;
 223     /** Inner class providing writelock */
 224     private final ReentrantReadWriteLock.WriteLock writerLock;
 225     /** Performs all synchronization mechanics */
 226     final Sync sync;
 227 
 228     /**
 229      * Creates a new {@code ReentrantReadWriteLock} with
 230      * default (nonfair) ordering properties.
 231      */
 232     public ReentrantReadWriteLock() {
 233         this(false);
 234     }
 235 
 236     /**
 237      * Creates a new {@code ReentrantReadWriteLock} with
 238      * the given fairness policy.
 239      *
 240      * @param fair {@code true} if this lock should use a fair ordering policy
 241      */
 242     public ReentrantReadWriteLock(boolean fair) {
 243         sync = fair ? new FairSync() : new NonfairSync();
 244         readerLock = new ReadLock(this);
 245         writerLock = new WriteLock(this);
 246     }
 247 
 248     public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
 249     public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
 250 
 251     /**
 252      * Synchronization implementation for ReentrantReadWriteLock.
 253      * Subclassed into fair and nonfair versions.
 254      */
 255     abstract static class Sync extends AbstractQueuedSynchronizer {
 256         private static final long serialVersionUID = 6317671515068378041L;
 257 
 258         /*
 259          * Read vs write count extraction constants and functions.
 260          * Lock state is logically divided into two unsigned shorts:
 261          * The lower one representing the exclusive (writer) lock hold count,
 262          * and the upper the shared (reader) hold count.
 263          */
 264 
 265         static final int SHARED_SHIFT   = 16;
 266         static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
 267         static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
 268         static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
 269 
 270         /** Returns the number of shared holds represented in count  */
 271         static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
 272         /** Returns the number of exclusive holds represented in count  */
 273         static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
 274 
 275         /**


 602                     }
 603                     return true;
 604                 }
 605             }
 606         }
 607 
 608         protected final boolean isHeldExclusively() {
 609             // While we must in general read state before owner,
 610             // we don't need to do so to check if current thread is owner
 611             return getExclusiveOwnerThread() == Thread.currentThread();
 612         }
 613 
 614         // Methods relayed to outer class
 615 
 616         final ConditionObject newCondition() {
 617             return new ConditionObject();
 618         }
 619 
 620         final Thread getOwner() {
 621             // Must read state before owner to ensure memory consistency
 622             return ((exclusiveCount(getState()) == 0) ?
 623                     null :
 624                     getExclusiveOwnerThread());
 625         }
 626 
 627         final int getReadLockCount() {
 628             return sharedCount(getState());
 629         }
 630 
 631         final boolean isWriteLocked() {
 632             return exclusiveCount(getState()) != 0;
 633         }
 634 
 635         final int getWriteHoldCount() {
 636             return isHeldExclusively() ? exclusiveCount(getState()) : 0;
 637         }
 638 
 639         final int getReadHoldCount() {
 640             if (getReadLockCount() == 0)
 641                 return 0;
 642 


 653             return count;
 654         }
 655 
 656         /**
 657          * Reconstitute this lock instance from a stream
 658          * @param s the stream
 659          */
 660         private void readObject(java.io.ObjectInputStream s)
 661             throws java.io.IOException, ClassNotFoundException {
 662             s.defaultReadObject();
 663             readHolds = new ThreadLocalHoldCounter();
 664             setState(0); // reset to unlocked state
 665         }
 666 
 667         final int getCount() { return getState(); }
 668     }
 669 
 670     /**
 671      * Nonfair version of Sync
 672      */
 673     static final class NonfairSync extends Sync {
 674         private static final long serialVersionUID = -8159625535654395037L;
 675         final boolean writerShouldBlock() {
 676             return false; // writers can always barge
 677         }
 678         final boolean readerShouldBlock() {
 679             /* As a heuristic to avoid indefinite writer starvation,
 680              * block if the thread that momentarily appears to be head
 681              * of queue, if one exists, is a waiting writer.  This is
 682              * only a probabilistic effect since a new reader will not
 683              * block if there is a waiting writer behind other enabled
 684              * readers that have not yet drained from the queue.
 685              */
 686             return apparentlyFirstQueuedIsExclusive();
 687         }
 688     }
 689 
 690     /**
 691      * Fair version of Sync
 692      */
 693     static final class FairSync extends Sync {
 694         private static final long serialVersionUID = -2274990926593161451L;
 695         final boolean writerShouldBlock() {
 696             return hasQueuedPredecessors();
 697         }
 698         final boolean readerShouldBlock() {
 699             return hasQueuedPredecessors();
 700         }
 701     }
 702 
 703     /**
 704      * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
 705      */
 706     public static class ReadLock implements Lock, java.io.Serializable {
 707         private static final long serialVersionUID = -5992448646407690164L;
 708         private final Sync sync;
 709 
 710         /**
 711          * Constructor for use by subclasses
 712          *
 713          * @param lock the outer lock object


 851          *
 852          * </ul> then {@link InterruptedException} is thrown and the
 853          * current thread's interrupted status is cleared.
 854          *
 855          * <p>If the specified waiting time elapses then the value
 856          * {@code false} is returned.  If the time is less than or
 857          * equal to zero, the method will not wait at all.
 858          *
 859          * <p>In this implementation, as this method is an explicit
 860          * interruption point, preference is given to responding to
 861          * the interrupt over normal or reentrant acquisition of the
 862          * lock, and over reporting the elapse of the waiting time.
 863          *
 864          * @param timeout the time to wait for the read lock
 865          * @param unit the time unit of the timeout argument
 866          * @return {@code true} if the read lock was acquired
 867          * @throws InterruptedException if the current thread is interrupted
 868          * @throws NullPointerException if the time unit is null
 869          *
 870          */
 871         public boolean tryLock(long timeout, TimeUnit unit)
 872                 throws InterruptedException {
 873             return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
 874         }
 875 
 876         /**
 877          * Attempts to release this lock.
 878          *
 879          * <p> If the number of readers is now zero then the lock
 880          * is made available for write lock attempts.
 881          */
 882         public  void unlock() {
 883             sync.releaseShared(1);
 884         }
 885 
 886         /**
 887          * Throws {@code UnsupportedOperationException} because
 888          * {@code ReadLocks} do not support conditions.
 889          *
 890          * @throws UnsupportedOperationException always
 891          */
 892         public Condition newCondition() {


1093          * {@code false} is returned.  If the time is less than or
1094          * equal to zero, the method will not wait at all.
1095          *
1096          * <p>In this implementation, as this method is an explicit
1097          * interruption point, preference is given to responding to
1098          * the interrupt over normal or reentrant acquisition of the
1099          * lock, and over reporting the elapse of the waiting time.
1100          *
1101          * @param timeout the time to wait for the write lock
1102          * @param unit the time unit of the timeout argument
1103          *
1104          * @return {@code true} if the lock was free and was acquired
1105          * by the current thread, or the write lock was already held by the
1106          * current thread; and {@code false} if the waiting time
1107          * elapsed before the lock could be acquired.
1108          *
1109          * @throws InterruptedException if the current thread is interrupted
1110          * @throws NullPointerException if the time unit is null
1111          *
1112          */
1113         public boolean tryLock(long timeout, TimeUnit unit)
1114                 throws InterruptedException {
1115             return sync.tryAcquireNanos(1, unit.toNanos(timeout));
1116         }
1117 
1118         /**
1119          * Attempts to release this lock.
1120          *
1121          * <p>If the current thread is the holder of this lock then
1122          * the hold count is decremented. If the hold count is now
1123          * zero then the lock is released.  If the current thread is
1124          * not the holder of this lock then {@link
1125          * IllegalMonitorStateException} is thrown.
1126          *
1127          * @throws IllegalMonitorStateException if the current thread does not
1128          * hold this lock.
1129          */
1130         public void unlock() {
1131             sync.release(1);
1132         }
1133 
1134         /**