1. /*
  2. * @(#)ReentrantReadWriteLock.java 1.7 04/07/14
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.concurrent.locks;
  8. import java.util.concurrent.*;
  9. import java.util.concurrent.atomic.*;
  10. import java.util.*;
  11. /**
  12. * An implementation of {@link ReadWriteLock} supporting similar
  13. * semantics to {@link ReentrantLock}.
  14. * <p>This class has the following properties:
  15. *
  16. * <ul>
  17. * <li><b>Acquisition order</b>
  18. *
  19. * <p> This class does not impose a reader or writer preference
  20. * ordering for lock access. However, it does support an optional
  21. * <em>fairness</em> policy. When constructed as fair, threads
  22. * contend for entry using an approximately arrival-order policy. When
  23. * the write lock is released either the longest-waiting single writer
  24. * will be assigned the write lock, or if there is a reader waiting
  25. * longer than any writer, the set of readers will be assigned the
  26. * read lock. When constructed as non-fair, the order of entry to the
  27. * lock need not be in arrival order. In either case, if readers are
  28. * active and a writer enters the lock then no subsequent readers will
  29. * be granted the read lock until after that writer has acquired and
  30. * released the write lock.
  31. *
  32. * <li><b>Reentrancy</b>
  33. * <p>This lock allows both readers and writers to reacquire read or
  34. * write locks in the style of a {@link ReentrantLock}. Readers are not
  35. * allowed until all write locks held by the writing thread have been
  36. * released.
  37. * <p>Additionally, a writer can acquire the read lock - but not vice-versa.
  38. * Among other applications, reentrancy can be useful when
  39. * write locks are held during calls or callbacks to methods that
  40. * perform reads under read locks.
  41. * If a reader tries to acquire the write lock it will never succeed.
  42. *
  43. * <li><b>Lock downgrading</b>
  44. * <p>Reentrancy also allows downgrading from the write lock to a read lock,
  45. * by acquiring the write lock, then the read lock and then releasing the
  46. * write lock. However, upgrading from a read lock to the write lock is
  47. * <b>not</b> possible.
  48. *
  49. * <li><b>Interruption of lock acquisition</b>
  50. * <p>The read lock and write lock both support interruption during lock
  51. * acquisition.
  52. *
  53. * <li><b>{@link Condition} support</b>
  54. * <p>The write lock provides a {@link Condition} implementation that
  55. * behaves in the same way, with respect to the write lock, as the
  56. * {@link Condition} implementation provided by
  57. * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
  58. * This {@link Condition} can, of course, only be used with the write lock.
  59. * <p>The read lock does not support a {@link Condition} and
  60. * <tt>readLock().newCondition()</tt> throws
  61. * <tt>UnsupportedOperationException</tt>.
  62. *
  63. * <li><b>Instrumentation</b>
  64. * <P> This class supports methods to determine whether locks
  65. * are held or contended. These methods are designed for monitoring
  66. * system state, not for synchronization control.
  67. * </ul>
  68. *
  69. * <p> Serialization of this class behaves in the same way as built-in
  70. * locks: a deserialized lock is in the unlocked state, regardless of
  71. * its state when serialized.
  72. *
  73. * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
  74. * reentrancy to perform lock downgrading after updating a cache (exception
  75. * handling is elided for simplicity):
  76. * <pre>
  77. * class CachedData {
  78. * Object data;
  79. * volatile boolean cacheValid;
  80. * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  81. *
  82. * void processCachedData() {
  83. * rwl.readLock().lock();
  84. * if (!cacheValid) {
  85. * // upgrade lock manually
  86. * rwl.readLock().unlock(); // must unlock first to obtain writelock
  87. * rwl.writeLock().lock();
  88. * if (!cacheValid) { // recheck
  89. * data = ...
  90. * cacheValid = true;
  91. * }
  92. * // downgrade lock
  93. * rwl.readLock().lock(); // reacquire read without giving up write lock
  94. * rwl.writeLock().unlock(); // unlock write, still hold read
  95. * }
  96. *
  97. * use(data);
  98. * rwl.readLock().unlock();
  99. * }
  100. * }
  101. * </pre>
  102. *
  103. * ReentrantReadWriteLocks can be used to improve concurrency in some
  104. * uses of some kinds of Collections. This is typically worthwhile
  105. * only when the collections are expected to be large, accessed by
  106. * more reader threads than writer threads, and entail operations with
  107. * overhead that outweighs synchronization overhead. For example, here
  108. * is a class using a TreeMap that is expected to be large and
  109. * concurrently accessed.
  110. *
  111. * <pre>
  112. * class RWDictionary {
  113. * private final Map<String, Data> m = new TreeMap<String, Data>();
  114. * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  115. * private final Lock r = rwl.readLock();
  116. * private final Lock w = rwl.writeLock();
  117. *
  118. * public Data get(String key) {
  119. * r.lock(); try { return m.get(key); } finally { r.unlock(); }
  120. * }
  121. * public String[] allKeys() {
  122. * r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }
  123. * }
  124. * public Data put(String key, Data value) {
  125. * w.lock(); try { return m.put(key, value); } finally { w.unlock(); }
  126. * }
  127. * public void clear() {
  128. * w.lock(); try { m.clear(); } finally { w.unlock(); }
  129. * }
  130. * }
  131. * </pre>
  132. *
  133. *
  134. * <h3>Implementation Notes</h3>
  135. *
  136. * <p>A reentrant write lock intrinsically defines an owner and can
  137. * only be released by the thread that acquired it. In contrast, in
  138. * this implementation, the read lock has no concept of ownership, and
  139. * there is no requirement that the thread releasing a read lock is
  140. * the same as the one that acquired it. However, this property is
  141. * not guaranteed to hold in future implementations of this class.
  142. *
  143. * <p> This lock supports a maximum of 65536 recursive write locks
  144. * and 65536 read locks. Attempts to exceed these limits result in
  145. * {@link Error} throws from locking methods.
  146. *
  147. * @since 1.5
  148. * @author Doug Lea
  149. *
  150. */
  151. public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
  152. private static final long serialVersionUID = -6992448646407690164L;
  153. /** Inner class providing readlock */
  154. private final ReentrantReadWriteLock.ReadLock readerLock;
  155. /** Inner class providing writelock */
  156. private final ReentrantReadWriteLock.WriteLock writerLock;
  157. /** Performs all synchronization mechanics */
  158. private final Sync sync;
  159. /**
  160. * Creates a new <tt>ReentrantReadWriteLock</tt> with
  161. * default ordering properties.
  162. */
  163. public ReentrantReadWriteLock() {
  164. sync = new NonfairSync();
  165. readerLock = new ReadLock(this);
  166. writerLock = new WriteLock(this);
  167. }
  168. /**
  169. * Creates a new <tt>ReentrantReadWriteLock</tt> with
  170. * the given fairness policy.
  171. *
  172. * @param fair true if this lock should use a fair ordering policy
  173. */
  174. public ReentrantReadWriteLock(boolean fair) {
  175. sync = (fair)? new FairSync() : new NonfairSync();
  176. readerLock = new ReadLock(this);
  177. writerLock = new WriteLock(this);
  178. }
  179. public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
  180. public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
  181. /*
  182. * Read vs write count extraction constants and functions.
  183. * Lock state is logically divided into two shorts: The lower
  184. * one representing the exclusive (writer) lock hold count,
  185. * and the upper the shared (reader) hold count.
  186. */
  187. static final int SHARED_SHIFT = 16;
  188. static final int SHARED_UNIT = (1 << SHARED_SHIFT);
  189. static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
  190. /** Returns the number of shared holds represented in count */
  191. static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
  192. /** Returns the number of exclusive holds represented in count */
  193. static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
  194. /**
  195. * Synchronization implementation for ReentrantReadWriteLock.
  196. * Subclassed into fair and nonfair versions.
  197. */
  198. abstract static class Sync extends AbstractQueuedSynchronizer {
  199. /** Current (exclusive) owner thread */
  200. transient Thread owner;
  201. /**
  202. * Perform write lock. Allows fast path in non-fair version.
  203. */
  204. abstract void wlock();
  205. /**
  206. * Perform non-fair tryLock for write. tryAcquire is
  207. * implemented in subclasses, but both versions need nonfair
  208. * try for trylock method
  209. */
  210. final boolean nonfairTryAcquire(int acquires) {
  211. // mask out readlocks if called from condition methods
  212. acquires = exclusiveCount(acquires);
  213. Thread current = Thread.currentThread();
  214. int c = getState();
  215. int w = exclusiveCount(c);
  216. if (w + acquires >= SHARED_UNIT)
  217. throw new Error("Maximum lock count exceeded");
  218. if (c != 0 && (w == 0 || current != owner))
  219. return false;
  220. if (!compareAndSetState(c, c + acquires))
  221. return false;
  222. owner = current;
  223. return true;
  224. }
  225. /**
  226. * Perform nonfair tryLock for read.
  227. */
  228. final int nonfairTryAcquireShared(int acquires) {
  229. for (;;) {
  230. int c = getState();
  231. int nextc = c + (acquires << SHARED_SHIFT);
  232. if (nextc < c)
  233. throw new Error("Maximum lock count exceeded");
  234. if (exclusiveCount(c) != 0 &&
  235. owner != Thread.currentThread())
  236. return -1;
  237. if (compareAndSetState(c, nextc))
  238. return 1;
  239. // Recheck count if lost CAS
  240. }
  241. }
  242. protected final boolean tryRelease(int releases) {
  243. Thread current = Thread.currentThread();
  244. int c = getState();
  245. if (owner != current)
  246. throw new IllegalMonitorStateException();
  247. int nextc = c - releases;
  248. boolean free = false;
  249. if (exclusiveCount(c) == releases) {
  250. free = true;
  251. owner = null;
  252. }
  253. setState(nextc);
  254. return free;
  255. }
  256. protected final boolean tryReleaseShared(int releases) {
  257. for (;;) {
  258. int c = getState();
  259. int nextc = c - (releases << SHARED_SHIFT);
  260. if (nextc < 0)
  261. throw new IllegalMonitorStateException();
  262. if (compareAndSetState(c, nextc))
  263. return nextc == 0;
  264. }
  265. }
  266. protected final boolean isHeldExclusively() {
  267. return exclusiveCount(getState()) != 0 &&
  268. owner == Thread.currentThread();
  269. }
  270. // Methods relayed to outer class
  271. final ConditionObject newCondition() {
  272. return new ConditionObject();
  273. }
  274. final Thread getOwner() {
  275. int c = exclusiveCount(getState());
  276. Thread o = owner;
  277. return (c == 0)? null : o;
  278. }
  279. final int getReadLockCount() {
  280. return sharedCount(getState());
  281. }
  282. final boolean isWriteLocked() {
  283. return exclusiveCount(getState()) != 0;
  284. }
  285. final int getWriteHoldCount() {
  286. int c = exclusiveCount(getState());
  287. Thread o = owner;
  288. return (o == Thread.currentThread())? c : 0;
  289. }
  290. /**
  291. * Reconstitute this lock instance from a stream
  292. * @param s the stream
  293. */
  294. private void readObject(java.io.ObjectInputStream s)
  295. throws java.io.IOException, ClassNotFoundException {
  296. s.defaultReadObject();
  297. setState(0); // reset to unlocked state
  298. }
  299. final int getCount() { return getState(); }
  300. }
  301. /**
  302. * Nonfair version of Sync
  303. */
  304. final static class NonfairSync extends Sync {
  305. protected final boolean tryAcquire(int acquires) {
  306. return nonfairTryAcquire(acquires);
  307. }
  308. protected final int tryAcquireShared(int acquires) {
  309. return nonfairTryAcquireShared(acquires);
  310. }
  311. // Use fastpath for main write lock method
  312. final void wlock() {
  313. if (compareAndSetState(0, 1))
  314. owner = Thread.currentThread();
  315. else
  316. acquire(1);
  317. }
  318. }
  319. /**
  320. * Fair version of Sync
  321. */
  322. final static class FairSync extends Sync {
  323. protected final boolean tryAcquire(int acquires) {
  324. // mask out readlocks if called from condition methods
  325. acquires = exclusiveCount(acquires);
  326. Thread current = Thread.currentThread();
  327. Thread first;
  328. int c = getState();
  329. int w = exclusiveCount(c);
  330. if (w + acquires >= SHARED_UNIT)
  331. throw new Error("Maximum lock count exceeded");
  332. if ((w == 0 || current != owner) &&
  333. (c != 0 ||
  334. ((first = getFirstQueuedThread()) != null &&
  335. first != current)))
  336. return false;
  337. if (!compareAndSetState(c, c + acquires))
  338. return false;
  339. owner = current;
  340. return true;
  341. }
  342. protected final int tryAcquireShared(int acquires) {
  343. Thread current = Thread.currentThread();
  344. for (;;) {
  345. int c = getState();
  346. if (exclusiveCount(c) != 0) {
  347. if (owner != current)
  348. return -1;
  349. } else {
  350. Thread first = getFirstQueuedThread();
  351. if (first != null && first != current)
  352. return -1;
  353. }
  354. int nextc = c + (acquires << SHARED_SHIFT);
  355. if (nextc < c)
  356. throw new Error("Maximum lock count exceeded");
  357. if (compareAndSetState(c, nextc))
  358. return 1;
  359. // Recheck count if lost CAS
  360. }
  361. }
  362. final void wlock() { // no fast path
  363. acquire(1);
  364. }
  365. }
  366. /**
  367. * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
  368. */
  369. public static class ReadLock implements Lock, java.io.Serializable {
  370. private static final long serialVersionUID = -5992448646407690164L;
  371. private final Sync sync;
  372. /**
  373. * Constructor for use by subclasses
  374. * @param lock the outer lock object
  375. * @throws NullPointerException if lock null
  376. */
  377. protected ReadLock(ReentrantReadWriteLock lock) {
  378. sync = lock.sync;
  379. }
  380. /**
  381. * Acquires the read lock.
  382. *
  383. * <p>Acquires the read lock if the write lock is not held by
  384. * another thread and returns immediately.
  385. *
  386. * <p>If the write lock is held by another thread then
  387. * the current thread becomes disabled for thread scheduling
  388. * purposes and lies dormant until the read lock has been acquired.
  389. */
  390. public void lock() {
  391. sync.acquireShared(1);
  392. }
  393. /**
  394. * Acquires the read lock unless the current thread is
  395. * {@link Thread#interrupt interrupted}.
  396. *
  397. * <p>Acquires the read lock if the write lock is not held
  398. * by another thread and returns immediately.
  399. *
  400. * <p>If the write lock is held by another thread then the
  401. * current thread becomes disabled for thread scheduling
  402. * purposes and lies dormant until one of two things happens:
  403. *
  404. * <ul>
  405. *
  406. * <li>The read lock is acquired by the current thread; or
  407. *
  408. * <li>Some other thread {@link Thread#interrupt interrupts}
  409. * the current thread.
  410. *
  411. * </ul>
  412. *
  413. * <p>If the current thread:
  414. *
  415. * <ul>
  416. *
  417. * <li>has its interrupted status set on entry to this method; or
  418. *
  419. * <li>is {@link Thread#interrupt interrupted} while acquiring
  420. * the read lock,
  421. *
  422. * </ul>
  423. *
  424. * then {@link InterruptedException} is thrown and the current
  425. * thread's interrupted status is cleared.
  426. *
  427. * <p>In this implementation, as this method is an explicit
  428. * interruption point, preference is given to responding to
  429. * the interrupt over normal or reentrant acquisition of the
  430. * lock.
  431. *
  432. * @throws InterruptedException if the current thread is interrupted
  433. */
  434. public void lockInterruptibly() throws InterruptedException {
  435. sync.acquireSharedInterruptibly(1);
  436. }
  437. /**
  438. * Acquires the read lock only if the write lock is not held by
  439. * another thread at the time of invocation.
  440. *
  441. * <p>Acquires the read lock if the write lock is not held by
  442. * another thread and returns immediately with the value
  443. * <tt>true</tt>. Even when this lock has been set to use a
  444. * fair ordering policy, a call to <tt>tryLock()</tt>
  445. * <em>will</em> immediately acquire the read lock if it is
  446. * available, whether or not other threads are currently
  447. * waiting for the read lock. This "barging" behavior
  448. * can be useful in certain circumstances, even though it
  449. * breaks fairness. If you want to honor the fairness setting
  450. * for this lock, then use {@link #tryLock(long, TimeUnit)
  451. * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
  452. * (it also detects interruption).
  453. *
  454. * <p>If the write lock is held by another thread then
  455. * this method will return immediately with the value
  456. * <tt>false</tt>.
  457. *
  458. * @return <tt>true</tt> if the read lock was acquired.
  459. */
  460. public boolean tryLock() {
  461. return sync.nonfairTryAcquireShared(1) >= 0;
  462. }
  463. /**
  464. * Acquires the read lock if the write lock is not held by
  465. * another thread within the given waiting time and the
  466. * current thread has not been {@link Thread#interrupt
  467. * interrupted}.
  468. *
  469. * <p>Acquires the read lock if the write lock is not held by
  470. * another thread and returns immediately with the value
  471. * <tt>true</tt>. If this lock has been set to use a fair
  472. * ordering policy then an available lock <em>will not</em> be
  473. * acquired if any other threads are waiting for the
  474. * lock. This is in contrast to the {@link #tryLock()}
  475. * method. If you want a timed <tt>tryLock</tt> that does
  476. * permit barging on a fair lock then combine the timed and
  477. * un-timed forms together:
  478. *
  479. * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
  480. * </pre>
  481. *
  482. * <p>If the write lock is held by another thread then the
  483. * current thread becomes disabled for thread scheduling
  484. * purposes and lies dormant until one of three things happens:
  485. *
  486. * <ul>
  487. *
  488. * <li>The read lock is acquired by the current thread; or
  489. *
  490. * <li>Some other thread {@link Thread#interrupt interrupts} the current
  491. * thread; or
  492. *
  493. * <li>The specified waiting time elapses
  494. *
  495. * </ul>
  496. *
  497. * <p>If the read lock is acquired then the value <tt>true</tt> is
  498. * returned.
  499. *
  500. * <p>If the current thread:
  501. *
  502. * <ul>
  503. *
  504. * <li>has its interrupted status set on entry to this method; or
  505. *
  506. * <li>is {@link Thread#interrupt interrupted} while acquiring
  507. * the read lock,
  508. *
  509. * </ul> then {@link InterruptedException} is thrown and the
  510. * current thread's interrupted status is cleared.
  511. *
  512. * <p>If the specified waiting time elapses then the value
  513. * <tt>false</tt> is returned. If the time is less than or
  514. * equal to zero, the method will not wait at all.
  515. *
  516. * <p>In this implementation, as this method is an explicit
  517. * interruption point, preference is given to responding to
  518. * the interrupt over normal or reentrant acquisition of the
  519. * lock, and over reporting the elapse of the waiting time.
  520. *
  521. * @param timeout the time to wait for the read lock
  522. * @param unit the time unit of the timeout argument
  523. *
  524. * @return <tt>true</tt> if the read lock was acquired.
  525. *
  526. * @throws InterruptedException if the current thread is interrupted
  527. * @throws NullPointerException if unit is null
  528. *
  529. */
  530. public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
  531. return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
  532. }
  533. /**
  534. * Attempts to release this lock.
  535. *
  536. * <p> If the number of readers is now zero then the lock
  537. * is made available for write lock attempts.
  538. */
  539. public void unlock() {
  540. sync.releaseShared(1);
  541. }
  542. /**
  543. * Throws <tt>UnsupportedOperationException</tt> because
  544. * <tt>ReadLocks</tt> do not support conditions.
  545. * @throws UnsupportedOperationException always
  546. */
  547. public Condition newCondition() {
  548. throw new UnsupportedOperationException();
  549. }
  550. /**
  551. * Returns a string identifying this lock, as well as its lock state.
  552. * The state, in brackets, includes the String
  553. * "Read locks =" followed by the number of held
  554. * read locks.
  555. * @return a string identifying this lock, as well as its lock state.
  556. */
  557. public String toString() {
  558. int r = sync.getReadLockCount();
  559. return super.toString() +
  560. "[Read locks = " + r + "]";
  561. }
  562. }
  563. /**
  564. * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
  565. */
  566. public static class WriteLock implements Lock, java.io.Serializable {
  567. private static final long serialVersionUID = -4992448646407690164L;
  568. private final Sync sync;
  569. /**
  570. * Constructor for use by subclasses
  571. * @param lock the outer lock object
  572. * @throws NullPointerException if lock null
  573. */
  574. protected WriteLock(ReentrantReadWriteLock lock) {
  575. sync = lock.sync;
  576. }
  577. /**
  578. * Acquire the write lock.
  579. *
  580. * <p>Acquires the write lock if neither the read nor write lock
  581. * are held by another thread
  582. * and returns immediately, setting the write lock hold count to
  583. * one.
  584. *
  585. * <p>If the current thread already holds the write lock then the
  586. * hold count is incremented by one and the method returns
  587. * immediately.
  588. *
  589. * <p>If the lock is held by another thread then the current
  590. * thread becomes disabled for thread scheduling purposes and
  591. * lies dormant until the write lock has been acquired, at which
  592. * time the write lock hold count is set to one.
  593. */
  594. public void lock() {
  595. sync.wlock();
  596. }
  597. /**
  598. * Acquires the write lock unless the current thread is {@link
  599. * Thread#interrupt interrupted}.
  600. *
  601. * <p>Acquires the write lock if neither the read nor write lock
  602. * are held by another thread
  603. * and returns immediately, setting the write lock hold count to
  604. * one.
  605. *
  606. * <p>If the current thread already holds this lock then the
  607. * hold count is incremented by one and the method returns
  608. * immediately.
  609. *
  610. * <p>If the lock is held by another thread then the current
  611. * thread becomes disabled for thread scheduling purposes and
  612. * lies dormant until one of two things happens:
  613. *
  614. * <ul>
  615. *
  616. * <li>The write lock is acquired by the current thread; or
  617. *
  618. * <li>Some other thread {@link Thread#interrupt interrupts}
  619. * the current thread.
  620. *
  621. * </ul>
  622. *
  623. * <p>If the write lock is acquired by the current thread then the
  624. * lock hold count is set to one.
  625. *
  626. * <p>If the current thread:
  627. *
  628. * <ul>
  629. *
  630. * <li>has its interrupted status set on entry to this method;
  631. * or
  632. *
  633. * <li>is {@link Thread#interrupt interrupted} while acquiring
  634. * the write lock,
  635. *
  636. * </ul>
  637. *
  638. * then {@link InterruptedException} is thrown and the current
  639. * thread's interrupted status is cleared.
  640. *
  641. * <p>In this implementation, as this method is an explicit
  642. * interruption point, preference is given to responding to
  643. * the interrupt over normal or reentrant acquisition of the
  644. * lock.
  645. *
  646. * @throws InterruptedException if the current thread is interrupted
  647. */
  648. public void lockInterruptibly() throws InterruptedException {
  649. sync.acquireInterruptibly(1);
  650. }
  651. /**
  652. * Acquires the write lock only if it is not held by another thread
  653. * at the time of invocation.
  654. *
  655. * <p>Acquires the write lock if neither the read nor write lock
  656. * are held by another thread
  657. * and returns immediately with the value <tt>true</tt>,
  658. * setting the write lock hold count to one. Even when this lock has
  659. * been set to use a fair ordering policy, a call to
  660. * <tt>tryLock()</tt> <em>will</em> immediately acquire the
  661. * lock if it is available, whether or not other threads are
  662. * currently waiting for the write lock. This "barging"
  663. * behavior can be useful in certain circumstances, even
  664. * though it breaks fairness. If you want to honor the
  665. * fairness setting for this lock, then use {@link
  666. * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
  667. * which is almost equivalent (it also detects interruption).
  668. *
  669. * <p> If the current thread already holds this lock then the
  670. * hold count is incremented by one and the method returns
  671. * <tt>true</tt>.
  672. *
  673. * <p>If the lock is held by another thread then this method
  674. * will return immediately with the value <tt>false</tt>.
  675. *
  676. * @return <tt>true</tt> if the lock was free and was acquired
  677. * by the current thread, or the write lock was already held
  678. * by the current thread; and <tt>false</tt> otherwise.
  679. */
  680. public boolean tryLock( ) {
  681. return sync.nonfairTryAcquire(1);
  682. }
  683. /**
  684. * Acquires the write lock if it is not held by another thread
  685. * within the given waiting time and the current thread has
  686. * not been {@link Thread#interrupt interrupted}.
  687. *
  688. * <p>Acquires the write lock if neither the read nor write lock
  689. * are held by another thread
  690. * and returns immediately with the value <tt>true</tt>,
  691. * setting the write lock hold count to one. If this lock has been
  692. * set to use a fair ordering policy then an available lock
  693. * <em>will not</em> be acquired if any other threads are
  694. * waiting for the write lock. This is in contrast to the {@link
  695. * #tryLock()} method. If you want a timed <tt>tryLock</tt>
  696. * that does permit barging on a fair lock then combine the
  697. * timed and un-timed forms together:
  698. *
  699. * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
  700. * </pre>
  701. *
  702. * <p>If the current thread already holds this lock then the
  703. * hold count is incremented by one and the method returns
  704. * <tt>true</tt>.
  705. *
  706. * <p>If the lock is held by another thread then the current
  707. * thread becomes disabled for thread scheduling purposes and
  708. * lies dormant until one of three things happens:
  709. *
  710. * <ul>
  711. *
  712. * <li>The write lock is acquired by the current thread; or
  713. *
  714. * <li>Some other thread {@link Thread#interrupt interrupts}
  715. * the current thread; or
  716. *
  717. * <li>The specified waiting time elapses
  718. *
  719. * </ul>
  720. *
  721. * <p>If the write lock is acquired then the value <tt>true</tt> is
  722. * returned and the write lock hold count is set to one.
  723. *
  724. * <p>If the current thread:
  725. *
  726. * <ul>
  727. *
  728. * <li>has its interrupted status set on entry to this method;
  729. * or
  730. *
  731. * <li>is {@link Thread#interrupt interrupted} while acquiring
  732. * the write lock,
  733. *
  734. * </ul>
  735. *
  736. * then {@link InterruptedException} is thrown and the current
  737. * thread's interrupted status is cleared.
  738. *
  739. * <p>If the specified waiting time elapses then the value
  740. * <tt>false</tt> is returned. If the time is less than or
  741. * equal to zero, the method will not wait at all.
  742. *
  743. * <p>In this implementation, as this method is an explicit
  744. * interruption point, preference is given to responding to
  745. * the interrupt over normal or reentrant acquisition of the
  746. * lock, and over reporting the elapse of the waiting time.
  747. *
  748. * @param timeout the time to wait for the write lock
  749. * @param unit the time unit of the timeout argument
  750. *
  751. * @return <tt>true</tt> if the lock was free and was acquired
  752. * by the current thread, or the write lock was already held by the
  753. * current thread; and <tt>false</tt> if the waiting time
  754. * elapsed before the lock could be acquired.
  755. *
  756. * @throws InterruptedException if the current thread is interrupted
  757. * @throws NullPointerException if unit is null
  758. *
  759. */
  760. public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
  761. return sync.tryAcquireNanos(1, unit.toNanos(timeout));
  762. }
  763. /**
  764. * Attempts to release this lock.
  765. *
  766. * <p>If the current thread is the holder of this lock then
  767. * the hold count is decremented. If the hold count is now
  768. * zero then the lock is released. If the current thread is
  769. * not the holder of this lock then {@link
  770. * IllegalMonitorStateException} is thrown.
  771. * @throws IllegalMonitorStateException if the current thread does not
  772. * hold this lock.
  773. */
  774. public void unlock() {
  775. sync.release(1);
  776. }
  777. /**
  778. * Returns a {@link Condition} instance for use with this
  779. * {@link Lock} instance.
  780. * <p>The returned {@link Condition} instance supports the same
  781. * usages as do the {@link Object} monitor methods ({@link
  782. * Object#wait() wait}, {@link Object#notify notify}, and {@link
  783. * Object#notifyAll notifyAll}) when used with the built-in
  784. * monitor lock.
  785. *
  786. * <ul>
  787. *
  788. * <li>If this write lock is not held when any {@link
  789. * Condition} method is called then an {@link
  790. * IllegalMonitorStateException} is thrown. (Read locks are
  791. * held independently of write locks, so are not checked or
  792. * affected. However it is essentially always an error to
  793. * invoke a condition waiting method when the current thread
  794. * has also acquired read locks, since other threads that
  795. * could unblock it will not be able to acquire the write
  796. * lock.)
  797. *
  798. * <li>When the condition {@link Condition#await() waiting}
  799. * methods are called the write lock is released and, before
  800. * they return, the write lock is reacquired and the lock hold
  801. * count restored to what it was when the method was called.
  802. *
  803. * <li>If a thread is {@link Thread#interrupt interrupted} while
  804. * waiting then the wait will terminate, an {@link
  805. * InterruptedException} will be thrown, and the thread's
  806. * interrupted status will be cleared.
  807. *
  808. * <li> Waiting threads are signalled in FIFO order.
  809. *
  810. * <li>The ordering of lock reacquisition for threads returning
  811. * from waiting methods is the same as for threads initially
  812. * acquiring the lock, which is in the default case not specified,
  813. * but for <em>fair</em> locks favors those threads that have been
  814. * waiting the longest.
  815. *
  816. * </ul>
  817. * @return the Condition object
  818. */
  819. public Condition newCondition() {
  820. return sync.newCondition();
  821. }
  822. /**
  823. * Returns a string identifying this lock, as well as its lock
  824. * state. The state, in brackets includes either the String
  825. * "Unlocked" or the String "Locked by"
  826. * followed by the {@link Thread#getName} of the owning thread.
  827. * @return a string identifying this lock, as well as its lock state.
  828. */
  829. public String toString() {
  830. Thread owner = sync.getOwner();
  831. return super.toString() + ((owner == null) ?
  832. "[Unlocked]" :
  833. "[Locked by thread " + owner.getName() + "]");
  834. }
  835. }
  836. // Instrumentation and status
  837. /**
  838. * Returns true if this lock has fairness set true.
  839. * @return true if this lock has fairness set true.
  840. */
  841. public final boolean isFair() {
  842. return sync instanceof FairSync;
  843. }
  844. /**
  845. * Returns the thread that currently owns the write lock, or
  846. * <tt>null</tt> if not owned. Note that the owner may be
  847. * momentarily <tt>null</tt> even if there are threads trying to
  848. * acquire the lock but have not yet done so. This method is
  849. * designed to facilitate construction of subclasses that provide
  850. * more extensive lock monitoring facilities.
  851. * @return the owner, or <tt>null</tt> if not owned.
  852. */
  853. protected Thread getOwner() {
  854. return sync.getOwner();
  855. }
  856. /**
  857. * Queries the number of read locks held for this lock. This
  858. * method is designed for use in monitoring system state, not for
  859. * synchronization control.
  860. * @return the number of read locks held.
  861. */
  862. public int getReadLockCount() {
  863. return sync.getReadLockCount();
  864. }
  865. /**
  866. * Queries if the write lock is held by any thread. This method is
  867. * designed for use in monitoring system state, not for
  868. * synchronization control.
  869. * @return <tt>true</tt> if any thread holds the write lock and
  870. * <tt>false</tt> otherwise.
  871. */
  872. public boolean isWriteLocked() {
  873. return sync.isWriteLocked();
  874. }
  875. /**
  876. * Queries if the write lock is held by the current thread.
  877. * @return <tt>true</tt> if the current thread holds the write lock and
  878. * <tt>false</tt> otherwise.
  879. */
  880. public boolean isWriteLockedByCurrentThread() {
  881. return sync.isHeldExclusively();
  882. }
  883. /**
  884. * Queries the number of reentrant write holds on this lock by the
  885. * current thread. A writer thread has a hold on a lock for
  886. * each lock action that is not matched by an unlock action.
  887. *
  888. * @return the number of holds on the write lock by the current thread,
  889. * or zero if the write lock is not held by the current thread.
  890. */
  891. public int getWriteHoldCount() {
  892. return sync.getWriteHoldCount();
  893. }
  894. /**
  895. * Returns a collection containing threads that may be waiting to
  896. * acquire the write lock. Because the actual set of threads may
  897. * change dynamically while constructing this result, the returned
  898. * collection is only a best-effort estimate. The elements of the
  899. * returned collection are in no particular order. This method is
  900. * designed to facilitate construction of subclasses that provide
  901. * more extensive lock monitoring facilities.
  902. * @return the collection of threads
  903. */
  904. protected Collection<Thread> getQueuedWriterThreads() {
  905. return sync.getExclusiveQueuedThreads();
  906. }
  907. /**
  908. * Returns a collection containing threads that may be waiting to
  909. * acquire the read lock. Because the actual set of threads may
  910. * change dynamically while constructing this result, the returned
  911. * collection is only a best-effort estimate. The elements of the
  912. * returned collection are in no particular order. This method is
  913. * designed to facilitate construction of subclasses that provide
  914. * more extensive lock monitoring facilities.
  915. * @return the collection of threads
  916. */
  917. protected Collection<Thread> getQueuedReaderThreads() {
  918. return sync.getSharedQueuedThreads();
  919. }
  920. /**
  921. * Queries whether any threads are waiting to acquire the read or
  922. * write lock. Note that because cancellations may occur at any
  923. * time, a <tt>true</tt> return does not guarantee that any other
  924. * thread will ever acquire a lock. This method is designed
  925. * primarily for use in monitoring of the system state.
  926. *
  927. * @return true if there may be other threads waiting to acquire
  928. * the lock.
  929. */
  930. public final boolean hasQueuedThreads() {
  931. return sync.hasQueuedThreads();
  932. }
  933. /**
  934. * Queries whether the given thread is waiting to acquire either
  935. * the read or write lock. Note that because cancellations may
  936. * occur at any time, a <tt>true</tt> return does not guarantee
  937. * that this thread will ever acquire a lock. This method is
  938. * designed primarily for use in monitoring of the system state.
  939. *
  940. * @param thread the thread
  941. * @return true if the given thread is queued waiting for this lock.
  942. * @throws NullPointerException if thread is null
  943. */
  944. public final boolean hasQueuedThread(Thread thread) {
  945. return sync.isQueued(thread);
  946. }
  947. /**
  948. * Returns an estimate of the number of threads waiting to acquire
  949. * either the read or write lock. The value is only an estimate
  950. * because the number of threads may change dynamically while this
  951. * method traverses internal data structures. This method is
  952. * designed for use in monitoring of the system state, not for
  953. * synchronization control.
  954. * @return the estimated number of threads waiting for this lock
  955. */
  956. public final int getQueueLength() {
  957. return sync.getQueueLength();
  958. }
  959. /**
  960. * Returns a collection containing threads that may be waiting to
  961. * acquire either the read or write lock. Because the actual set
  962. * of threads may change dynamically while constructing this
  963. * result, the returned collection is only a best-effort estimate.
  964. * The elements of the returned collection are in no particular
  965. * order. This method is designed to facilitate construction of
  966. * subclasses that provide more extensive monitoring facilities.
  967. * @return the collection of threads
  968. */
  969. protected Collection<Thread> getQueuedThreads() {
  970. return sync.getQueuedThreads();
  971. }
  972. /**
  973. * Queries whether any threads are waiting on the given condition
  974. * associated with the write lock. Note that because timeouts and
  975. * interrupts may occur at any time, a <tt>true</tt> return does
  976. * not guarantee that a future <tt>signal</tt> will awaken any
  977. * threads. This method is designed primarily for use in
  978. * monitoring of the system state.
  979. * @param condition the condition
  980. * @return <tt>true</tt> if there are any waiting threads.
  981. * @throws IllegalMonitorStateException if this lock
  982. * is not held
  983. * @throws IllegalArgumentException if the given condition is
  984. * not associated with this lock
  985. * @throws NullPointerException if condition null
  986. */
  987. public boolean hasWaiters(Condition condition) {
  988. if (condition == null)
  989. throw new NullPointerException();
  990. if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
  991. throw new IllegalArgumentException("not owner");
  992. return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
  993. }
  994. /**
  995. * Returns an estimate of the number of threads waiting on the
  996. * given condition associated with the write lock. Note that because
  997. * timeouts and interrupts may occur at any time, the estimate
  998. * serves only as an upper bound on the actual number of waiters.
  999. * This method is designed for use in monitoring of the system
  1000. * state, not for synchronization control.
  1001. * @param condition the condition
  1002. * @return the estimated number of waiting threads.
  1003. * @throws IllegalMonitorStateException if this lock
  1004. * is not held
  1005. * @throws IllegalArgumentException if the given condition is
  1006. * not associated with this lock
  1007. * @throws NullPointerException if condition null
  1008. */
  1009. public int getWaitQueueLength(Condition condition) {
  1010. if (condition == null)
  1011. throw new NullPointerException();
  1012. if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
  1013. throw new IllegalArgumentException("not owner");
  1014. return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
  1015. }
  1016. /**
  1017. * Returns a collection containing those threads that may be
  1018. * waiting on the given condition associated with the write lock.
  1019. * Because the actual set of threads may change dynamically while
  1020. * constructing this result, the returned collection is only a
  1021. * best-effort estimate. The elements of the returned collection
  1022. * are in no particular order. This method is designed to
  1023. * facilitate construction of subclasses that provide more
  1024. * extensive condition monitoring facilities.
  1025. * @param condition the condition
  1026. * @return the collection of threads
  1027. * @throws IllegalMonitorStateException if this lock
  1028. * is not held
  1029. * @throws IllegalArgumentException if the given condition is
  1030. * not associated with this lock
  1031. * @throws NullPointerException if condition null
  1032. */
  1033. protected Collection<Thread> getWaitingThreads(Condition condition) {
  1034. if (condition == null)
  1035. throw new NullPointerException();
  1036. if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
  1037. throw new IllegalArgumentException("not owner");
  1038. return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
  1039. }
  1040. /**
  1041. * Returns a string identifying this lock, as well as its lock state.
  1042. * The state, in brackets, includes the String "Write locks ="
  1043. * followed by the number of reentrantly held write locks, and the
  1044. * String "Read locks =" followed by the number of held
  1045. * read locks.
  1046. * @return a string identifying this lock, as well as its lock state.
  1047. */
  1048. public String toString() {
  1049. int c = sync.getCount();
  1050. int w = exclusiveCount(c);
  1051. int r = sharedCount(c);
  1052. return super.toString() +
  1053. "[Write locks = " + w + ", Read locks = " + r + "]";
  1054. }
  1055. }