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 /**
|