/* * Written by Doug Lea and Martin Buchholz * with assistance from members of JCP JSR-166 Expert Group and * released to the public domain, as explained at * http://creativecommons.org/publicdomain/zero/1.0/ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.StampedLock; import junit.framework.Test; import junit.framework.TestSuite; public class StampedLockTest extends JSR166TestCase { public static void main(String[] args) { main(suite(), args); } public static Test suite() { return new TestSuite(StampedLockTest.class); } /** * A runnable calling writeLockInterruptibly */ class InterruptibleLockRunnable extends CheckedRunnable { final StampedLock lock; InterruptibleLockRunnable(StampedLock l) { lock = l; } public void realRun() throws InterruptedException { lock.writeLockInterruptibly(); } } /** * A runnable calling writeLockInterruptibly that expects to be * interrupted */ class InterruptedLockRunnable extends CheckedInterruptedRunnable { final StampedLock lock; InterruptedLockRunnable(StampedLock l) { lock = l; } public void realRun() throws InterruptedException { lock.writeLockInterruptibly(); } } /** * Releases write lock, checking isWriteLocked before and after */ void releaseWriteLock(StampedLock lock, long s) { assertTrue(lock.isWriteLocked()); lock.unlockWrite(s); assertFalse(lock.isWriteLocked()); } /** * Constructed StampedLock is in unlocked state */ public void testConstructor() { StampedLock lock; lock = new StampedLock(); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); } /** * write-locking and read-locking an unlocked lock succeed */ public void testLock() { StampedLock lock = new StampedLock(); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); long s = lock.writeLock(); assertTrue(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); lock.unlockWrite(s); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); long rs = lock.readLock(); assertFalse(lock.isWriteLocked()); assertTrue(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 1); lock.unlockRead(rs); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); } /** * unlock releases either a read or write lock */ public void testUnlock() { StampedLock lock = new StampedLock(); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); long s = lock.writeLock(); assertTrue(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); lock.unlock(s); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); long rs = lock.readLock(); assertFalse(lock.isWriteLocked()); assertTrue(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 1); lock.unlock(rs); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); } /** * tryUnlockRead/Write succeeds if locked in associated mode else * returns false */ public void testTryUnlock() { StampedLock lock = new StampedLock(); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); long s = lock.writeLock(); assertTrue(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); assertFalse(lock.tryUnlockRead()); assertTrue(lock.tryUnlockWrite()); assertFalse(lock.tryUnlockWrite()); assertFalse(lock.tryUnlockRead()); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); long rs = lock.readLock(); assertFalse(lock.isWriteLocked()); assertTrue(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 1); assertFalse(lock.tryUnlockWrite()); assertTrue(lock.tryUnlockRead()); assertFalse(lock.tryUnlockRead()); assertFalse(lock.tryUnlockWrite()); assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(lock.getReadLockCount(), 0); } /** * write-unlocking an unlocked lock throws IllegalMonitorStateException */ public void testWriteUnlock_IMSE() { StampedLock lock = new StampedLock(); try { lock.unlockWrite(0L); shouldThrow(); } catch (IllegalMonitorStateException success) {} } /** * write-unlocking an unlocked lock throws IllegalMonitorStateException */ public void testWriteUnlock_IMSE2() { StampedLock lock = new StampedLock(); long s = lock.writeLock(); lock.unlockWrite(s); try { lock.unlockWrite(s); shouldThrow(); } catch (IllegalMonitorStateException success) {} } /** * write-unlocking after readlock throws IllegalMonitorStateException */ public void testWriteUnlock_IMSE3() { StampedLock lock = new StampedLock(); long s = lock.readLock(); try { lock.unlockWrite(s); shouldThrow(); } catch (IllegalMonitorStateException success) {} } /** * read-unlocking an unlocked lock throws IllegalMonitorStateException */ public void testReadUnlock_IMSE() { StampedLock lock = new StampedLock(); long s = lock.readLock(); lock.unlockRead(s); try { lock.unlockRead(s); shouldThrow(); } catch (IllegalMonitorStateException success) {} } /** * read-unlocking an unlocked lock throws IllegalMonitorStateException */ public void testReadUnlock_IMSE2() { StampedLock lock = new StampedLock(); try { lock.unlockRead(0L); shouldThrow(); } catch (IllegalMonitorStateException success) {} } /** * read-unlocking after writeLock throws IllegalMonitorStateException */ public void testReadUnlock_IMSE3() { StampedLock lock = new StampedLock(); long s = lock.writeLock(); try { lock.unlockRead(s); shouldThrow(); } catch (IllegalMonitorStateException success) {} } /** * validate(0) fails */ public void testValidate0() { StampedLock lock = new StampedLock(); assertFalse(lock.validate(0L)); } /** * A stamp obtained from a successful lock operation validates */ public void testValidate() throws InterruptedException { StampedLock lock = new StampedLock(); long s = lock.writeLock(); assertTrue(lock.validate(s)); lock.unlockWrite(s); s = lock.readLock(); assertTrue(lock.validate(s)); lock.unlockRead(s); assertTrue((s = lock.tryWriteLock()) != 0L); assertTrue(lock.validate(s)); lock.unlockWrite(s); assertTrue((s = lock.tryReadLock()) != 0L); assertTrue(lock.validate(s)); lock.unlockRead(s); assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); assertTrue(lock.validate(s)); lock.unlockWrite(s); assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); assertTrue(lock.validate(s)); lock.unlockRead(s); assertTrue((s = lock.tryOptimisticRead()) != 0L); } /** * A stamp obtained from an unsuccessful lock operation does not validate */ public void testValidate2() throws InterruptedException { StampedLock lock = new StampedLock(); long s; assertTrue((s = lock.writeLock()) != 0L); assertTrue(lock.validate(s)); assertFalse(lock.validate(lock.tryWriteLock())); assertFalse(lock.validate(lock.tryWriteLock(10L, MILLISECONDS))); assertFalse(lock.validate(lock.tryReadLock())); assertFalse(lock.validate(lock.tryReadLock(10L, MILLISECONDS))); assertFalse(lock.validate(lock.tryOptimisticRead())); lock.unlockWrite(s); } /** * writeLockInterruptibly is interruptible */ public void testWriteLockInterruptibly_Interruptible() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { running.countDown(); lock.writeLockInterruptibly(); }}); running.await(); waitForThreadToEnterWaitState(t, 100); t.interrupt(); awaitTermination(t); releaseWriteLock(lock, s); } /** * timed tryWriteLock is interruptible */ public void testWriteTryLock_Interruptible() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { running.countDown(); lock.tryWriteLock(2 * LONG_DELAY_MS, MILLISECONDS); }}); running.await(); waitForThreadToEnterWaitState(t, 100); t.interrupt(); awaitTermination(t); releaseWriteLock(lock, s); } /** * readLockInterruptibly is interruptible */ public void testReadLockInterruptibly_Interruptible() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { running.countDown(); lock.readLockInterruptibly(); }}); running.await(); waitForThreadToEnterWaitState(t, 100); t.interrupt(); awaitTermination(t); releaseWriteLock(lock, s); } /** * timed tryReadLock is interruptible */ public void testReadTryLock_Interruptible() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { running.countDown(); lock.tryReadLock(2 * LONG_DELAY_MS, MILLISECONDS); }}); running.await(); waitForThreadToEnterWaitState(t, 100); t.interrupt(); awaitTermination(t); releaseWriteLock(lock, s); } /** * tryWriteLock on an unlocked lock succeeds */ public void testWriteTryLock() { final StampedLock lock = new StampedLock(); long s = lock.tryWriteLock(); assertTrue(s != 0L); assertTrue(lock.isWriteLocked()); long s2 = lock.tryWriteLock(); assertEquals(s2, 0L); releaseWriteLock(lock, s); } /** * tryWriteLock fails if locked */ public void testWriteTryLockWhenLocked() { final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { long ws = lock.tryWriteLock(); assertTrue(ws == 0L); }}); awaitTermination(t); releaseWriteLock(lock, s); } /** * tryReadLock fails if write-locked */ public void testReadTryLockWhenLocked() { final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { long rs = lock.tryReadLock(); assertEquals(rs, 0L); }}); awaitTermination(t); releaseWriteLock(lock, s); } /** * Multiple threads can hold a read lock when not write-locked */ public void testMultipleReadLocks() { final StampedLock lock = new StampedLock(); final long s = lock.readLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { long s2 = lock.tryReadLock(); assertTrue(s2 != 0L); lock.unlockRead(s2); long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS); assertTrue(s3 != 0L); lock.unlockRead(s3); long s4 = lock.readLock(); lock.unlockRead(s4); }}); awaitTermination(t); lock.unlockRead(s); } /** * A writelock succeeds only after a reading thread unlocks */ public void testWriteAfterReadLock() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long rs = lock.readLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { running.countDown(); long s = lock.writeLock(); lock.unlockWrite(s); }}); running.await(); waitForThreadToEnterWaitState(t, 100); assertFalse(lock.isWriteLocked()); lock.unlockRead(rs); awaitTermination(t); assertFalse(lock.isWriteLocked()); } /** * A writelock succeeds only after reading threads unlock */ public void testWriteAfterMultipleReadLocks() { final StampedLock lock = new StampedLock(); long s = lock.readLock(); Thread t1 = newStartedThread(new CheckedRunnable() { public void realRun() { long rs = lock.readLock(); lock.unlockRead(rs); }}); awaitTermination(t1); Thread t2 = newStartedThread(new CheckedRunnable() { public void realRun() { long ws = lock.writeLock(); lock.unlockWrite(ws); }}); assertFalse(lock.isWriteLocked()); lock.unlockRead(s); awaitTermination(t2); assertFalse(lock.isWriteLocked()); } /** * Readlocks succeed only after a writing thread unlocks */ public void testReadAfterWriteLock() { final StampedLock lock = new StampedLock(); final long s = lock.writeLock(); Thread t1 = newStartedThread(new CheckedRunnable() { public void realRun() { long rs = lock.readLock(); lock.unlockRead(rs); }}); Thread t2 = newStartedThread(new CheckedRunnable() { public void realRun() { long rs = lock.readLock(); lock.unlockRead(rs); }}); releaseWriteLock(lock, s); awaitTermination(t1); awaitTermination(t2); } /** * tryReadLock succeeds if readlocked but not writelocked */ public void testTryLockWhenReadLocked() { final StampedLock lock = new StampedLock(); long s = lock.readLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { long rs = lock.tryReadLock(); threadAssertTrue(rs != 0L); lock.unlockRead(rs); }}); awaitTermination(t); lock.unlockRead(s); } /** * tryWriteLock fails when readlocked */ public void testWriteTryLockWhenReadLocked() { final StampedLock lock = new StampedLock(); long s = lock.readLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { long ws = lock.tryWriteLock(); threadAssertEquals(ws, 0L); }}); awaitTermination(t); lock.unlockRead(s); } /** * timed tryWriteLock times out if locked */ public void testWriteTryLock_Timeout() { final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { long startTime = System.nanoTime(); long timeoutMillis = 10; long ws = lock.tryWriteLock(timeoutMillis, MILLISECONDS); assertEquals(ws, 0L); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); }}); awaitTermination(t); releaseWriteLock(lock, s); } /** * timed tryReadLock times out if write-locked */ public void testReadTryLock_Timeout() { final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { long startTime = System.nanoTime(); long timeoutMillis = 10; long rs = lock.tryReadLock(timeoutMillis, MILLISECONDS); assertEquals(rs, 0L); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); }}); awaitTermination(t); assertTrue(lock.isWriteLocked()); lock.unlockWrite(s); } /** * writeLockInterruptibly succeeds if unlocked, else is interruptible */ public void testWriteLockInterruptibly() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s = lock.writeLockInterruptibly(); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { running.countDown(); lock.writeLockInterruptibly(); }}); running.await(); waitForThreadToEnterWaitState(t, 100); t.interrupt(); assertTrue(lock.isWriteLocked()); awaitTermination(t); releaseWriteLock(lock, s); } /** * readLockInterruptibly succeeds if lock free else is interruptible */ public void testReadLockInterruptibly() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s; s = lock.readLockInterruptibly(); lock.unlockRead(s); s = lock.writeLockInterruptibly(); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { running.countDown(); lock.readLockInterruptibly(); }}); running.await(); waitForThreadToEnterWaitState(t, 100); t.interrupt(); awaitTermination(t); releaseWriteLock(lock, s); } /** * A serialized lock deserializes as unlocked */ public void testSerialization() { StampedLock lock = new StampedLock(); lock.writeLock(); StampedLock clone = serialClone(lock); assertTrue(lock.isWriteLocked()); assertFalse(clone.isWriteLocked()); long s = clone.writeLock(); assertTrue(clone.isWriteLocked()); clone.unlockWrite(s); assertFalse(clone.isWriteLocked()); } /** * toString indicates current lock state */ public void testToString() { StampedLock lock = new StampedLock(); assertTrue(lock.toString().contains("Unlocked")); long s = lock.writeLock(); assertTrue(lock.toString().contains("Write-locked")); lock.unlockWrite(s); s = lock.readLock(); assertTrue(lock.toString().contains("Read-locks")); } /** * tryOptimisticRead succeeds and validates if unlocked, fails if locked */ public void testValidateOptimistic() throws InterruptedException { StampedLock lock = new StampedLock(); long s, p; assertTrue((p = lock.tryOptimisticRead()) != 0L); assertTrue(lock.validate(p)); assertTrue((s = lock.writeLock()) != 0L); assertFalse((p = lock.tryOptimisticRead()) != 0L); assertTrue(lock.validate(s)); lock.unlockWrite(s); assertTrue((p = lock.tryOptimisticRead()) != 0L); assertTrue(lock.validate(p)); assertTrue((s = lock.readLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryOptimisticRead()) != 0L); assertTrue(lock.validate(p)); lock.unlockRead(s); assertTrue((s = lock.tryWriteLock()) != 0L); assertTrue(lock.validate(s)); assertFalse((p = lock.tryOptimisticRead()) != 0L); lock.unlockWrite(s); assertTrue((s = lock.tryReadLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryOptimisticRead()) != 0L); lock.unlockRead(s); assertTrue(lock.validate(p)); assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); assertFalse((p = lock.tryOptimisticRead()) != 0L); assertTrue(lock.validate(s)); lock.unlockWrite(s); assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryOptimisticRead()) != 0L); lock.unlockRead(s); assertTrue((p = lock.tryOptimisticRead()) != 0L); } /** * tryOptimisticRead stamp does not validate if a write lock intervenes */ public void testValidateOptimisticWriteLocked() { StampedLock lock = new StampedLock(); long s, p; assertTrue((p = lock.tryOptimisticRead()) != 0L); assertTrue((s = lock.writeLock()) != 0L); assertFalse(lock.validate(p)); assertFalse((p = lock.tryOptimisticRead()) != 0L); assertTrue(lock.validate(s)); lock.unlockWrite(s); } /** * tryOptimisticRead stamp does not validate if a write lock * intervenes in another thread */ public void testValidateOptimisticWriteLocked2() throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s, p; assertTrue((p = lock.tryOptimisticRead()) != 0L); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { lock.writeLockInterruptibly(); running.countDown(); lock.writeLockInterruptibly(); }}); running.await(); assertFalse(lock.validate(p)); assertFalse((p = lock.tryOptimisticRead()) != 0L); t.interrupt(); awaitTermination(t); } /** * tryConvertToOptimisticRead succeeds and validates if successfully locked, */ public void testTryConvertToOptimisticRead() throws InterruptedException { StampedLock lock = new StampedLock(); long s, p; assertEquals(0L, lock.tryConvertToOptimisticRead(0L)); assertTrue((s = lock.tryOptimisticRead()) != 0L); assertEquals(s, lock.tryConvertToOptimisticRead(s)); assertTrue(lock.validate(s)); assertTrue((s = lock.writeLock()) != 0L); assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); assertTrue(lock.validate(p)); assertTrue((s = lock.readLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); assertTrue(lock.validate(p)); assertTrue((s = lock.tryWriteLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); assertTrue(lock.validate(p)); assertTrue((s = lock.tryReadLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); assertTrue(lock.validate(p)); assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); assertTrue(lock.validate(p)); assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); assertTrue(lock.validate(p)); } /** * tryConvertToReadLock succeeds and validates if successfully locked * or lock free; */ public void testTryConvertToReadLock() throws InterruptedException { StampedLock lock = new StampedLock(); long s, p; s = 0L; assertFalse((p = lock.tryConvertToReadLock(s)) != 0L); assertTrue((s = lock.tryOptimisticRead()) != 0L); assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); lock.unlockRead(p); assertTrue((s = lock.writeLock()) != 0L); assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockRead(p); assertTrue((s = lock.readLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockRead(p); assertTrue((s = lock.tryWriteLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockRead(p); assertTrue((s = lock.tryReadLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockRead(p); assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockRead(p); assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockRead(p); } /** * tryConvertToWriteLock succeeds and validates if successfully locked * or lock free; */ public void testTryConvertToWriteLock() throws InterruptedException { StampedLock lock = new StampedLock(); long s, p; s = 0L; assertFalse((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue((s = lock.tryOptimisticRead()) != 0L); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); lock.unlockWrite(p); assertTrue((s = lock.writeLock()) != 0L); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockWrite(p); assertTrue((s = lock.readLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockWrite(p); assertTrue((s = lock.tryWriteLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockWrite(p); assertTrue((s = lock.tryReadLock()) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockWrite(p); assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockWrite(p); assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); assertTrue(lock.validate(s)); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue(lock.validate(p)); lock.unlockWrite(p); } /** * asWriteLock can be locked and unlocked */ public void testAsWriteLock() { StampedLock sl = new StampedLock(); Lock lock = sl.asWriteLock(); lock.lock(); assertFalse(lock.tryLock()); lock.unlock(); assertTrue(lock.tryLock()); } /** * asReadLock can be locked and unlocked */ public void testAsReadLock() { StampedLock sl = new StampedLock(); Lock lock = sl.asReadLock(); lock.lock(); lock.unlock(); assertTrue(lock.tryLock()); } /** * asReadWriteLock.writeLock can be locked and unlocked */ public void testAsReadWriteLockWriteLock() { StampedLock sl = new StampedLock(); Lock lock = sl.asReadWriteLock().writeLock(); lock.lock(); assertFalse(lock.tryLock()); lock.unlock(); assertTrue(lock.tryLock()); } /** * asReadWriteLock.readLock can be locked and unlocked */ public void testAsReadWriteLockReadLock() { StampedLock sl = new StampedLock(); Lock lock = sl.asReadWriteLock().readLock(); lock.lock(); lock.unlock(); assertTrue(lock.tryLock()); } /** * Lock.newCondition throws UnsupportedOperationException */ public void testLockViewsDoNotSupportConditions() { StampedLock sl = new StampedLock(); assertThrows(UnsupportedOperationException.class, () -> sl.asWriteLock().newCondition(), () -> sl.asReadLock().newCondition(), () -> sl.asReadWriteLock().writeLock().newCondition(), () -> sl.asReadWriteLock().readLock().newCondition()); } /** * Passing optimistic read stamps to unlock operations result in * IllegalMonitorStateException */ public void testCannotUnlockOptimisticReadStamps() { Runnable[] actions = { () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryOptimisticRead(); assertTrue(stamp != 0); sl.unlockRead(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryOptimisticRead(); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryOptimisticRead(); sl.writeLock(); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryOptimisticRead(); sl.readLock(); sl.unlockRead(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryOptimisticRead(); sl.readLock(); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); assertTrue(stamp != 0); sl.writeLock(); sl.unlockWrite(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); sl.writeLock(); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); sl.readLock(); sl.unlockRead(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); sl.readLock(); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); assertTrue(stamp != 0); sl.writeLock(); sl.unlockWrite(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); sl.writeLock(); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); sl.readLock(); sl.unlockRead(stamp); }, () -> { StampedLock sl = new StampedLock(); sl.readLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); assertTrue(stamp != 0); sl.readLock(); sl.unlockRead(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); sl.readLock(); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); sl.readLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); sl.readLock(); sl.unlock(stamp); }, }; assertThrows(IllegalMonitorStateException.class, actions); } }