| /* |
| * Written by Doug Lea with assistance from members of JCP JSR-166 |
| * Expert Group and released to the public domain, as explained at |
| * http://creativecommons.org/licenses/publicdomain |
| * Other contributors include Andrew Wright, Jeffrey Hayes, |
| * Pat Fisher, Mike Judd. |
| */ |
| |
| import junit.framework.*; |
| import java.util.concurrent.locks.*; |
| import java.util.concurrent.*; |
| import java.io.*; |
| import java.util.*; |
| |
| public class ReentrantReadWriteLockTest extends JSR166TestCase { |
| public static void main(String[] args) { |
| junit.textui.TestRunner.run (suite()); |
| } |
| public static Test suite() { |
| return new TestSuite(ReentrantReadWriteLockTest.class); |
| } |
| |
| /** |
| * A runnable calling lockInterruptibly |
| */ |
| class InterruptibleLockRunnable implements Runnable { |
| final ReentrantReadWriteLock lock; |
| InterruptibleLockRunnable(ReentrantReadWriteLock l) { lock = l; } |
| public void run() { |
| try { |
| lock.writeLock().lockInterruptibly(); |
| } catch(InterruptedException success){} |
| } |
| } |
| |
| |
| /** |
| * A runnable calling lockInterruptibly that expects to be |
| * interrupted |
| */ |
| class InterruptedLockRunnable implements Runnable { |
| final ReentrantReadWriteLock lock; |
| InterruptedLockRunnable(ReentrantReadWriteLock l) { lock = l; } |
| public void run() { |
| try { |
| lock.writeLock().lockInterruptibly(); |
| threadShouldThrow(); |
| } catch(InterruptedException success){} |
| } |
| } |
| |
| /** |
| * Subclass to expose protected methods |
| */ |
| static class PublicReentrantReadWriteLock extends ReentrantReadWriteLock { |
| PublicReentrantReadWriteLock() { super(); } |
| public Collection<Thread> getQueuedThreads() { |
| return super.getQueuedThreads(); |
| } |
| public Collection<Thread> getWaitingThreads(Condition c) { |
| return super.getWaitingThreads(c); |
| } |
| } |
| |
| /** |
| * Constructor sets given fairness, and is in unlocked state |
| */ |
| public void testConstructor() { |
| ReentrantReadWriteLock rl = new ReentrantReadWriteLock(); |
| assertFalse(rl.isFair()); |
| assertFalse(rl.isWriteLocked()); |
| assertEquals(0, rl.getReadLockCount()); |
| ReentrantReadWriteLock r2 = new ReentrantReadWriteLock(true); |
| assertTrue(r2.isFair()); |
| assertFalse(r2.isWriteLocked()); |
| assertEquals(0, r2.getReadLockCount()); |
| } |
| |
| /** |
| * write-locking and read-locking an unlocked lock succeed |
| */ |
| public void testLock() { |
| ReentrantReadWriteLock rl = new ReentrantReadWriteLock(); |
| rl.writeLock().lock(); |
| assertTrue(rl.isWriteLocked()); |
| assertTrue(rl.isWriteLockedByCurrentThread()); |
| assertEquals(0, rl.getReadLockCount()); |
| rl.writeLock().unlock(); |
| assertFalse(rl.isWriteLocked()); |
| assertFalse(rl.isWriteLockedByCurrentThread()); |
| assertEquals(0, rl.getReadLockCount()); |
| rl.readLock().lock(); |
| assertFalse(rl.isWriteLocked()); |
| assertFalse(rl.isWriteLockedByCurrentThread()); |
| assertEquals(1, rl.getReadLockCount()); |
| rl.readLock().unlock(); |
| assertFalse(rl.isWriteLocked()); |
| assertFalse(rl.isWriteLockedByCurrentThread()); |
| assertEquals(0, rl.getReadLockCount()); |
| } |
| |
| |
| /** |
| * locking an unlocked fair lock succeeds |
| */ |
| public void testFairLock() { |
| ReentrantReadWriteLock rl = new ReentrantReadWriteLock(true); |
| rl.writeLock().lock(); |
| assertTrue(rl.isWriteLocked()); |
| assertTrue(rl.isWriteLockedByCurrentThread()); |
| assertEquals(0, rl.getReadLockCount()); |
| rl.writeLock().unlock(); |
| assertFalse(rl.isWriteLocked()); |
| assertFalse(rl.isWriteLockedByCurrentThread()); |
| assertEquals(0, rl.getReadLockCount()); |
| rl.readLock().lock(); |
| assertFalse(rl.isWriteLocked()); |
| assertFalse(rl.isWriteLockedByCurrentThread()); |
| assertEquals(1, rl.getReadLockCount()); |
| rl.readLock().unlock(); |
| assertFalse(rl.isWriteLocked()); |
| assertFalse(rl.isWriteLockedByCurrentThread()); |
| assertEquals(0, rl.getReadLockCount()); |
| } |
| |
| /** |
| * getWriteHoldCount returns number of recursive holds |
| */ |
| public void testGetWriteHoldCount() { |
| ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| for(int i = 1; i <= SIZE; i++) { |
| lock.writeLock().lock(); |
| assertEquals(i,lock.getWriteHoldCount()); |
| } |
| for(int i = SIZE; i > 0; i--) { |
| lock.writeLock().unlock(); |
| assertEquals(i-1,lock.getWriteHoldCount()); |
| } |
| } |
| |
| |
| /** |
| * write-unlocking an unlocked lock throws IllegalMonitorStateException |
| */ |
| public void testUnlock_IllegalMonitorStateException() { |
| ReentrantReadWriteLock rl = new ReentrantReadWriteLock(); |
| try { |
| rl.writeLock().unlock(); |
| shouldThrow(); |
| } catch(IllegalMonitorStateException success){} |
| } |
| |
| |
| /** |
| * write-lockInterruptibly is interruptible |
| */ |
| public void testWriteLockInterruptibly_Interrupted() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lockInterruptibly(); |
| lock.writeLock().unlock(); |
| lock.writeLock().lockInterruptibly(); |
| lock.writeLock().unlock(); |
| } catch(InterruptedException success){} |
| } |
| }); |
| try { |
| lock.writeLock().lock(); |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().unlock(); |
| t.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timed write-tryLock is interruptible |
| */ |
| public void testWriteTryLock_Interrupted() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().tryLock(1000,TimeUnit.MILLISECONDS); |
| } catch(InterruptedException success){} |
| } |
| }); |
| try { |
| t.start(); |
| t.interrupt(); |
| lock.writeLock().unlock(); |
| t.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * read-lockInterruptibly is interruptible |
| */ |
| public void testReadLockInterruptibly_Interrupted() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.readLock().lockInterruptibly(); |
| } catch(InterruptedException success){} |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().unlock(); |
| t.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timed read-tryLock is interruptible |
| */ |
| public void testReadTryLock_Interrupted() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.readLock().tryLock(1000,TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch(InterruptedException success){} |
| } |
| }); |
| try { |
| t.start(); |
| t.interrupt(); |
| t.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * write-tryLock fails if locked |
| */ |
| public void testWriteTryLockWhenLocked() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| threadAssertFalse(lock.writeLock().tryLock()); |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.writeLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * read-tryLock fails if locked |
| */ |
| public void testReadTryLockWhenLocked() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| threadAssertFalse(lock.readLock().tryLock()); |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.writeLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Multiple threads can hold a read lock when not write-locked |
| */ |
| public void testMultipleReadLocks() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.readLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| threadAssertTrue(lock.readLock().tryLock()); |
| lock.readLock().unlock(); |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.readLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A writelock succeeds after reading threads unlock |
| */ |
| public void testWriteAfterMultipleReadLocks() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.readLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.readLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Readlocks succeed after a writing thread unlocks |
| */ |
| public void testReadAfterWriteLock() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Read trylock succeeds if write locked by current thread |
| */ |
| public void testReadHoldingWriteLock() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| assertTrue(lock.readLock().tryLock()); |
| lock.readLock().unlock(); |
| lock.writeLock().unlock(); |
| } |
| |
| /** |
| * Read lock succeeds if write locked by current thread even if |
| * other threads are waiting for readlock |
| */ |
| public void testReadHoldingWriteLock2() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| lock.writeLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Read lock succeeds if write locked by current thread even if |
| * other threads are waiting for writelock |
| */ |
| public void testReadHoldingWriteLock3() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| lock.writeLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * Write lock succeeds if write locked by current thread even if |
| * other threads are waiting for writelock |
| */ |
| public void testWriteHoldingWriteLock4() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| lock.writeLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * Fair Read trylock succeeds if write locked by current thread |
| */ |
| public void testReadHoldingWriteLockFair() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); |
| lock.writeLock().lock(); |
| assertTrue(lock.readLock().tryLock()); |
| lock.readLock().unlock(); |
| lock.writeLock().unlock(); |
| } |
| |
| /** |
| * Fair Read lock succeeds if write locked by current thread even if |
| * other threads are waiting for readlock |
| */ |
| public void testReadHoldingWriteLockFair2() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); |
| lock.writeLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| lock.writeLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * Fair Read lock succeeds if write locked by current thread even if |
| * other threads are waiting for writelock |
| */ |
| public void testReadHoldingWriteLockFair3() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); |
| lock.writeLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.readLock().lock(); |
| lock.readLock().unlock(); |
| lock.writeLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * Fair Write lock succeeds if write locked by current thread even if |
| * other threads are waiting for writelock |
| */ |
| public void testWriteHoldingWriteLockFair4() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); |
| lock.writeLock().lock(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.isWriteLockedByCurrentThread()); |
| assertTrue(lock.getWriteHoldCount() == 1); |
| lock.writeLock().lock(); |
| assertTrue(lock.getWriteHoldCount() == 2); |
| lock.writeLock().unlock(); |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| lock.writeLock().unlock(); |
| t1.join(MEDIUM_DELAY_MS); |
| t2.join(MEDIUM_DELAY_MS); |
| assertTrue(!t1.isAlive()); |
| assertTrue(!t2.isAlive()); |
| |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * Read tryLock succeeds if readlocked but not writelocked |
| */ |
| public void testTryLockWhenReadLocked() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.readLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| threadAssertTrue(lock.readLock().tryLock()); |
| lock.readLock().unlock(); |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.readLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| |
| /** |
| * write tryLock fails when readlocked |
| */ |
| public void testWriteTryLockWhenReadLocked() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.readLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| threadAssertFalse(lock.writeLock().tryLock()); |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.readLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * Fair Read tryLock succeeds if readlocked but not writelocked |
| */ |
| public void testTryLockWhenReadLockedFair() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); |
| lock.readLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| threadAssertTrue(lock.readLock().tryLock()); |
| lock.readLock().unlock(); |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.readLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| |
| /** |
| * Fair write tryLock fails when readlocked |
| */ |
| public void testWriteTryLockWhenReadLockedFair() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); |
| lock.readLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| threadAssertFalse(lock.writeLock().tryLock()); |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.readLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| |
| /** |
| * write timed tryLock times out if locked |
| */ |
| public void testWriteTryLock_Timeout() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| threadAssertFalse(lock.writeLock().tryLock(1, TimeUnit.MILLISECONDS)); |
| } catch (Exception ex) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.writeLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * read timed tryLock times out if write-locked |
| */ |
| public void testReadTryLock_Timeout() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| lock.writeLock().lock(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| threadAssertFalse(lock.readLock().tryLock(1, TimeUnit.MILLISECONDS)); |
| } catch (Exception ex) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| t.join(); |
| lock.writeLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * write lockInterruptibly succeeds if lock free else is interruptible |
| */ |
| public void testWriteLockInterruptibly() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| try { |
| lock.writeLock().lockInterruptibly(); |
| } catch(Exception e) { |
| unexpectedException(); |
| } |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lockInterruptibly(); |
| threadShouldThrow(); |
| } |
| catch(InterruptedException success) { |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.join(); |
| lock.writeLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * read lockInterruptibly succeeds if lock free else is interruptible |
| */ |
| public void testReadLockInterruptibly() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| try { |
| lock.writeLock().lockInterruptibly(); |
| } catch(Exception e) { |
| unexpectedException(); |
| } |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.readLock().lockInterruptibly(); |
| threadShouldThrow(); |
| } |
| catch(InterruptedException success) { |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| lock.writeLock().unlock(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Calling await without holding lock throws IllegalMonitorStateException |
| */ |
| public void testAwait_IllegalMonitor() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| try { |
| c.await(); |
| shouldThrow(); |
| } |
| catch (IllegalMonitorStateException success) { |
| } |
| catch (Exception ex) { |
| shouldThrow(); |
| } |
| } |
| |
| /** |
| * Calling signal without holding lock throws IllegalMonitorStateException |
| */ |
| public void testSignal_IllegalMonitor() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| try { |
| c.signal(); |
| shouldThrow(); |
| } |
| catch (IllegalMonitorStateException success) { |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * awaitNanos without a signal times out |
| */ |
| public void testAwaitNanos_Timeout() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| try { |
| lock.writeLock().lock(); |
| long t = c.awaitNanos(100); |
| assertTrue(t <= 0); |
| lock.writeLock().unlock(); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * timed await without a signal times out |
| */ |
| public void testAwait_Timeout() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| try { |
| lock.writeLock().lock(); |
| lock.writeLock().unlock(); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * awaitUntil without a signal times out |
| */ |
| public void testAwaitUntil_Timeout() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| try { |
| lock.writeLock().lock(); |
| java.util.Date d = new java.util.Date(); |
| lock.writeLock().unlock(); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * await returns when signalled |
| */ |
| public void testAwait() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| c.await(); |
| lock.writeLock().unlock(); |
| } |
| catch(InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| c.signal(); |
| lock.writeLock().unlock(); |
| t.join(SHORT_DELAY_MS); |
| assertFalse(t.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** A helper class for uninterruptible wait tests */ |
| class UninterruptableThread extends Thread { |
| private Lock lock; |
| private Condition c; |
| |
| public volatile boolean canAwake = false; |
| public volatile boolean interrupted = false; |
| public volatile boolean lockStarted = false; |
| |
| public UninterruptableThread(Lock lock, Condition c) { |
| this.lock = lock; |
| this.c = c; |
| } |
| |
| public synchronized void run() { |
| lock.lock(); |
| lockStarted = true; |
| |
| while (!canAwake) { |
| c.awaitUninterruptibly(); |
| } |
| |
| interrupted = isInterrupted(); |
| lock.unlock(); |
| } |
| } |
| |
| /** |
| * awaitUninterruptibly doesn't abort on interrupt |
| */ |
| public void testAwaitUninterruptibly() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| UninterruptableThread thread = new UninterruptableThread(lock.writeLock(), c); |
| |
| try { |
| thread.start(); |
| |
| while (!thread.lockStarted) { |
| Thread.sleep(100); |
| } |
| |
| lock.writeLock().lock(); |
| try { |
| thread.interrupt(); |
| thread.canAwake = true; |
| c.signal(); |
| } finally { |
| lock.writeLock().unlock(); |
| } |
| |
| thread.join(); |
| assertTrue(thread.interrupted); |
| assertFalse(thread.isAlive()); |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * await is interruptible |
| */ |
| public void testAwait_Interrupt() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| c.await(); |
| lock.writeLock().unlock(); |
| threadShouldThrow(); |
| } |
| catch(InterruptedException success) { |
| } |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(SHORT_DELAY_MS); |
| assertFalse(t.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * awaitNanos is interruptible |
| */ |
| public void testAwaitNanos_Interrupt() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| c.awaitNanos(SHORT_DELAY_MS * 2 * 1000000); |
| lock.writeLock().unlock(); |
| threadShouldThrow(); |
| } |
| catch(InterruptedException success) { |
| } |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(SHORT_DELAY_MS); |
| assertFalse(t.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * awaitUntil is interruptible |
| */ |
| public void testAwaitUntil_Interrupt() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| java.util.Date d = new java.util.Date(); |
| c.awaitUntil(new java.util.Date(d.getTime() + 10000)); |
| lock.writeLock().unlock(); |
| threadShouldThrow(); |
| } |
| catch(InterruptedException success) { |
| } |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(SHORT_DELAY_MS); |
| assertFalse(t.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * signalAll wakes up all threads |
| */ |
| public void testSignalAll() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| c.await(); |
| lock.writeLock().unlock(); |
| } |
| catch(InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| c.await(); |
| lock.writeLock().unlock(); |
| } |
| catch(InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| c.signalAll(); |
| lock.writeLock().unlock(); |
| t1.join(SHORT_DELAY_MS); |
| t2.join(SHORT_DELAY_MS); |
| assertFalse(t1.isAlive()); |
| assertFalse(t2.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * A serialized lock deserializes as unlocked |
| */ |
| public void testSerialization() { |
| ReentrantReadWriteLock l = new ReentrantReadWriteLock(); |
| l.readLock().lock(); |
| l.readLock().unlock(); |
| |
| try { |
| ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); |
| ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); |
| out.writeObject(l); |
| out.close(); |
| |
| ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); |
| ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); |
| ReentrantReadWriteLock r = (ReentrantReadWriteLock) in.readObject(); |
| r.readLock().lock(); |
| r.readLock().unlock(); |
| } catch(Exception e){ |
| e.printStackTrace(); |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * hasQueuedThreads reports whether there are waiting threads |
| */ |
| public void testhasQueuedThreads() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
| try { |
| assertFalse(lock.hasQueuedThreads()); |
| lock.writeLock().lock(); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.hasQueuedThreads()); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.hasQueuedThreads()); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.hasQueuedThreads()); |
| lock.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertFalse(lock.hasQueuedThreads()); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * hasQueuedThread(null) throws NPE |
| */ |
| public void testHasQueuedThreadNPE() { |
| final ReentrantReadWriteLock sync = new ReentrantReadWriteLock(); |
| try { |
| sync.hasQueuedThread(null); |
| shouldThrow(); |
| } catch (NullPointerException success) { |
| } |
| } |
| |
| /** |
| * hasQueuedThread reports whether a thread is queued. |
| */ |
| public void testHasQueuedThread() { |
| final ReentrantReadWriteLock sync = new ReentrantReadWriteLock(); |
| Thread t1 = new Thread(new InterruptedLockRunnable(sync)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(sync)); |
| try { |
| assertFalse(sync.hasQueuedThread(t1)); |
| assertFalse(sync.hasQueuedThread(t2)); |
| sync.writeLock().lock(); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(sync.hasQueuedThread(t1)); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(sync.hasQueuedThread(t1)); |
| assertTrue(sync.hasQueuedThread(t2)); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertFalse(sync.hasQueuedThread(t1)); |
| assertTrue(sync.hasQueuedThread(t2)); |
| sync.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertFalse(sync.hasQueuedThread(t1)); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertFalse(sync.hasQueuedThread(t2)); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * getQueueLength reports number of waiting threads |
| */ |
| public void testGetQueueLength() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
| try { |
| assertEquals(0, lock.getQueueLength()); |
| lock.writeLock().lock(); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(1, lock.getQueueLength()); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(2, lock.getQueueLength()); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(1, lock.getQueueLength()); |
| lock.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertEquals(0, lock.getQueueLength()); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getQueuedThreads includes waiting threads |
| */ |
| public void testGetQueuedThreads() { |
| final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); |
| Thread t1 = new Thread(new InterruptedLockRunnable(lock)); |
| Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); |
| try { |
| assertTrue(lock.getQueuedThreads().isEmpty()); |
| lock.writeLock().lock(); |
| assertTrue(lock.getQueuedThreads().isEmpty()); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.getQueuedThreads().contains(t1)); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.getQueuedThreads().contains(t1)); |
| assertTrue(lock.getQueuedThreads().contains(t2)); |
| t1.interrupt(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertFalse(lock.getQueuedThreads().contains(t1)); |
| assertTrue(lock.getQueuedThreads().contains(t2)); |
| lock.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| assertTrue(lock.getQueuedThreads().isEmpty()); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * hasWaiters throws NPE if null |
| */ |
| public void testHasWaitersNPE() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| try { |
| lock.hasWaiters(null); |
| shouldThrow(); |
| } catch (NullPointerException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getWaitQueueLength throws NPE if null |
| */ |
| public void testGetWaitQueueLengthNPE() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| try { |
| lock.getWaitQueueLength(null); |
| shouldThrow(); |
| } catch (NullPointerException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * getWaitingThreads throws NPE if null |
| */ |
| public void testGetWaitingThreadsNPE() { |
| final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); |
| try { |
| lock.getWaitingThreads(null); |
| shouldThrow(); |
| } catch (NullPointerException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * hasWaiters throws IAE if not owned |
| */ |
| public void testHasWaitersIAE() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock(); |
| try { |
| lock2.hasWaiters(c); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * hasWaiters throws IMSE if not locked |
| */ |
| public void testHasWaitersIMSE() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| try { |
| lock.hasWaiters(c); |
| shouldThrow(); |
| } catch (IllegalMonitorStateException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * getWaitQueueLength throws IAE if not owned |
| */ |
| public void testGetWaitQueueLengthIAE() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock(); |
| try { |
| lock2.getWaitQueueLength(c); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getWaitQueueLength throws IMSE if not locked |
| */ |
| public void testGetWaitQueueLengthIMSE() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| try { |
| lock.getWaitQueueLength(c); |
| shouldThrow(); |
| } catch (IllegalMonitorStateException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * getWaitingThreads throws IAE if not owned |
| */ |
| public void testGetWaitingThreadsIAE() { |
| final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| final PublicReentrantReadWriteLock lock2 = new PublicReentrantReadWriteLock(); |
| try { |
| lock2.getWaitingThreads(c); |
| shouldThrow(); |
| } catch (IllegalArgumentException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getWaitingThreads throws IMSE if not locked |
| */ |
| public void testGetWaitingThreadsIMSE() { |
| final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| try { |
| lock.getWaitingThreads(c); |
| shouldThrow(); |
| } catch (IllegalMonitorStateException success) { |
| } catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * hasWaiters returns true when a thread is waiting, else false |
| */ |
| public void testHasWaiters() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| threadAssertFalse(lock.hasWaiters(c)); |
| threadAssertEquals(0, lock.getWaitQueueLength(c)); |
| c.await(); |
| lock.writeLock().unlock(); |
| } |
| catch(InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| assertTrue(lock.hasWaiters(c)); |
| assertEquals(1, lock.getWaitQueueLength(c)); |
| c.signal(); |
| lock.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| assertFalse(lock.hasWaiters(c)); |
| assertEquals(0, lock.getWaitQueueLength(c)); |
| lock.writeLock().unlock(); |
| t.join(SHORT_DELAY_MS); |
| assertFalse(t.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * getWaitQueueLength returns number of waiting threads |
| */ |
| public void testGetWaitQueueLength() { |
| final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| final Condition c = (lock.writeLock().newCondition()); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| threadAssertFalse(lock.hasWaiters(c)); |
| threadAssertEquals(0, lock.getWaitQueueLength(c)); |
| c.await(); |
| lock.writeLock().unlock(); |
| } |
| catch(InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| assertTrue(lock.hasWaiters(c)); |
| assertEquals(1, lock.getWaitQueueLength(c)); |
| c.signal(); |
| lock.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| assertFalse(lock.hasWaiters(c)); |
| assertEquals(0, lock.getWaitQueueLength(c)); |
| lock.writeLock().unlock(); |
| t.join(SHORT_DELAY_MS); |
| assertFalse(t.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * getWaitingThreads returns only and all waiting threads |
| */ |
| public void testGetWaitingThreads() { |
| final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(); |
| final Condition c = lock.writeLock().newCondition(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| threadAssertTrue(lock.getWaitingThreads(c).isEmpty()); |
| c.await(); |
| lock.writeLock().unlock(); |
| } |
| catch(InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| try { |
| lock.writeLock().lock(); |
| threadAssertFalse(lock.getWaitingThreads(c).isEmpty()); |
| c.await(); |
| lock.writeLock().unlock(); |
| } |
| catch(InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| try { |
| lock.writeLock().lock(); |
| assertTrue(lock.getWaitingThreads(c).isEmpty()); |
| lock.writeLock().unlock(); |
| t1.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t2.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| assertTrue(lock.hasWaiters(c)); |
| assertTrue(lock.getWaitingThreads(c).contains(t1)); |
| assertTrue(lock.getWaitingThreads(c).contains(t2)); |
| c.signalAll(); |
| lock.writeLock().unlock(); |
| Thread.sleep(SHORT_DELAY_MS); |
| lock.writeLock().lock(); |
| assertFalse(lock.hasWaiters(c)); |
| assertTrue(lock.getWaitingThreads(c).isEmpty()); |
| lock.writeLock().unlock(); |
| t1.join(SHORT_DELAY_MS); |
| t2.join(SHORT_DELAY_MS); |
| assertFalse(t1.isAlive()); |
| assertFalse(t2.isAlive()); |
| } |
| catch (Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * toString indicates current lock state |
| */ |
| public void testToString() { |
| ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| String us = lock.toString(); |
| assertTrue(us.indexOf("Write locks = 0") >= 0); |
| assertTrue(us.indexOf("Read locks = 0") >= 0); |
| lock.writeLock().lock(); |
| String ws = lock.toString(); |
| assertTrue(ws.indexOf("Write locks = 1") >= 0); |
| assertTrue(ws.indexOf("Read locks = 0") >= 0); |
| lock.writeLock().unlock(); |
| lock.readLock().lock(); |
| lock.readLock().lock(); |
| String rs = lock.toString(); |
| assertTrue(rs.indexOf("Write locks = 0") >= 0); |
| assertTrue(rs.indexOf("Read locks = 2") >= 0); |
| } |
| |
| /** |
| * readLock.toString indicates current lock state |
| */ |
| public void testReadLockToString() { |
| ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| String us = lock.readLock().toString(); |
| assertTrue(us.indexOf("Read locks = 0") >= 0); |
| lock.readLock().lock(); |
| lock.readLock().lock(); |
| String rs = lock.readLock().toString(); |
| assertTrue(rs.indexOf("Read locks = 2") >= 0); |
| } |
| |
| /** |
| * writeLock.toString indicates current lock state |
| */ |
| public void testWriteLockToString() { |
| ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); |
| String us = lock.writeLock().toString(); |
| assertTrue(us.indexOf("Unlocked") >= 0); |
| lock.writeLock().lock(); |
| String ls = lock.writeLock().toString(); |
| assertTrue(ls.indexOf("Locked") >= 0); |
| } |
| |
| } |