public static void main(String[] args) { Position position = new Position(); StampedLock lock = new StampedLock(); Thread threadWriter = new Thread(new Writer(position, lock)); Thread threadReader = new Thread(new Reader(position, lock)); Thread threadOptReader = new Thread(new OptimisticReader(position, lock)); threadWriter.start(); threadReader.start(); threadOptReader.start(); try { threadWriter.join(); threadReader.join(); threadOptReader.join(); } catch (InterruptedException e) { e.printStackTrace(); } }
public static void main(String[] args) { Position position=new Position(); StampedLock lock=new StampedLock(); Thread threadWriter=new Thread(new Writer(position,lock)); Thread threadReader=new Thread(new Reader(position, lock)); Thread threadOptReader=new Thread(new OptimisticReader(position, lock)); threadWriter.start(); threadReader.start(); threadOptReader.start(); try { threadWriter.join(); threadReader.join(); threadOptReader.join(); } catch (InterruptedException e) { e.printStackTrace(); } }
static Reader interruptibleReader(final StampedLock sl, final long timeout, final TimeUnit unit, final Phaser gate) { return new Reader("InterruptibleReader") { public void run() { if (gate != null ) toTheStartingGate(gate); try { if (timeout < 0) stamp(sl.readLockInterruptibly()); else stamp(sl.tryReadLock(timeout, unit)); check(sl.validate(stamp())); check(sl.isReadLocked()); check(!sl.isWriteLocked()); } catch (Throwable x) { thrown(x); } finally { if (stamp() != 0L) sl.unlockRead(stamp()); } }}; }
static Reader interruptibleReaderView(final StampedLock sl, final long timeout, final TimeUnit unit, final Phaser gate) { return new Reader("InterruptibleReaderView") { public void run() { if (gate != null ) toTheStartingGate(gate); final Lock rl = sl.asReadLock(); try { if (timeout < 0) rl.lockInterruptibly(); else rl.tryLock(timeout, unit); stamp(1L); // got the lock check(sl.isReadLocked()); check(!sl.isWriteLocked()); } catch (Throwable x) { thrown(x); } finally { if (stamp() != 0L) rl.unlock(); } }}; }
static Writer interruptibleWriter(final StampedLock sl, final long timeout, final TimeUnit unit, final Phaser gate) { return new Writer("InterruptibleWriter") { public void run() { if (gate != null ) toTheStartingGate(gate); try { if (timeout < 0) stamp(sl.writeLockInterruptibly()); else stamp(sl.tryWriteLock(timeout, unit)); check(sl.validate(stamp())); check(!sl.isReadLocked()); check(sl.isWriteLocked()); } catch (Throwable x) { thrown(x); } finally { if (stamp() != 0L) sl.unlockWrite(stamp()); } }}; }
static Writer interruptibleWriterView(final StampedLock sl, final long timeout, final TimeUnit unit, final Phaser gate) { return new Writer("InterruptibleWriterView") { public void run() { if (gate != null ) toTheStartingGate(gate); Lock wl = sl.asWriteLock(); try { if (timeout < 0) wl.lockInterruptibly(); else wl.tryLock(timeout, unit); stamp(1L); // got the lock check(!sl.isReadLocked()); check(sl.isWriteLocked()); } catch (Throwable x) { thrown(x); } finally { if (stamp() != 0L) wl.unlock(); } }}; }
static Iterator<Reader> readerIterator(final StampedLock sl, final Phaser gate) { return new Iterator<Reader>() { int i = 0; boolean view = false; public boolean hasNext() { return true; } public Reader next() { switch ((i++)&7) { case 1: case 4: case 7: return reader(sl, gate, view ^= true); case 2: case 5: return interruptibleReader(sl, -1, SECONDS, gate, view ^= true); default: return interruptibleReader(sl, 30, SECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; }
static Iterator<Writer> writerIterator(final StampedLock sl, final Phaser gate) { return new Iterator<Writer>() { int i = 0; boolean view = false; public boolean hasNext() { return true; } public Writer next() { switch ((i++)&7) { case 1: case 4: case 7: return writer(sl, gate, view ^= true); case 2: case 5: return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true); default: return interruptibleWriter(sl, 30, SECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; }
/** * write-locking, then unlocking, an unlocked lock succeed */ public void testWriteLock_lockUnlock() { StampedLock lock = new StampedLock(); for (Function<StampedLock, Long> writeLocker : writeLockers()) for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { assertFalse(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(0, lock.getReadLockCount()); long s = writeLocker.apply(lock); assertValid(lock, s); assertTrue(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); assertEquals(0, lock.getReadLockCount()); writeUnlocker.accept(lock, s); assertUnlocked(lock); } }
/** * read-locking, then unlocking, an unlocked lock succeed */ public void testReadLock_lockUnlock() { StampedLock lock = new StampedLock(); for (Function<StampedLock, Long> readLocker : readLockers()) for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) { long s = 42; for (int i = 0; i < 2; i++) { s = assertValid(lock, readLocker.apply(lock)); assertFalse(lock.isWriteLocked()); assertTrue(lock.isReadLocked()); assertEquals(i + 1, lock.getReadLockCount()); } for (int i = 0; i < 2; i++) { assertFalse(lock.isWriteLocked()); assertTrue(lock.isReadLocked()); assertEquals(2 - i, lock.getReadLockCount()); readUnlocker.accept(lock, s); } assertUnlocked(lock); } }
/** * interruptible operations throw InterruptedException when write locked and interrupted */ public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() { final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Action[] interruptibleLockBlockingActions = { () -> lock.writeLockInterruptibly(), () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS), () -> lock.readLockInterruptibly(), () -> lock.tryReadLock(Long.MAX_VALUE, DAYS), () -> lock.asWriteLock().lockInterruptibly(), () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS), () -> lock.asReadLock().lockInterruptibly(), () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS), }; shuffle(interruptibleLockBlockingActions); assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions); }
/** * 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(); assertValid(lock, s2); lock.unlockRead(s2); long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS); assertValid(lock, s3); lock.unlockRead(s3); long s4 = lock.readLock(); assertValid(lock, s4); lock.unlockRead(s4); lock.asReadLock().lock(); lock.asReadLock().unlock(); lock.asReadLock().lockInterruptibly(); lock.asReadLock().unlock(); lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS); lock.asReadLock().unlock(); }}); awaitTermination(t); lock.unlockRead(s); }
/** * writeLock() succeeds only after a reading thread unlocks */ public void testWriteAfterReadLock() throws InterruptedException { final CountDownLatch aboutToLock = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long rs = lock.readLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { aboutToLock.countDown(); long s = lock.writeLock(); assertTrue(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); lock.unlockWrite(s); }}); await(aboutToLock); assertThreadBlocks(t, Thread.State.WAITING); assertFalse(lock.isWriteLocked()); assertTrue(lock.isReadLocked()); lock.unlockRead(rs); awaitTermination(t); assertUnlocked(lock); }
/** * 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); }}); assertTrue(lock.isReadLocked()); assertFalse(lock.isWriteLocked()); lock.unlockRead(s); awaitTermination(t2); assertUnlocked(lock); }
/** * readLock() succeed only after a writing thread unlocks */ public void testReadAfterWriteLock() { final StampedLock lock = new StampedLock(); final CountDownLatch threadsStarted = new CountDownLatch(2); final long s = lock.writeLock(); final Runnable acquireReleaseReadLock = new CheckedRunnable() { public void realRun() { threadsStarted.countDown(); long rs = lock.readLock(); assertTrue(lock.isReadLocked()); assertFalse(lock.isWriteLocked()); lock.unlockRead(rs); }}; Thread t1 = newStartedThread(acquireReleaseReadLock); Thread t2 = newStartedThread(acquireReleaseReadLock); await(threadsStarted); assertThreadBlocks(t1, Thread.State.WAITING); assertThreadBlocks(t2, Thread.State.WAITING); assertTrue(lock.isWriteLocked()); assertFalse(lock.isReadLocked()); releaseWriteLock(lock, s); awaitTermination(t1); awaitTermination(t2); assertUnlocked(lock); }
/** * tryOptimisticRead stamp does not validate if a write lock * intervenes in another thread */ public void testValidateOptimisticWriteLocked2() throws InterruptedException { final CountDownLatch locked = new CountDownLatch(1); final StampedLock lock = new StampedLock(); final long p = assertValid(lock, lock.tryOptimisticRead()); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { lock.writeLockInterruptibly(); locked.countDown(); lock.writeLockInterruptibly(); }}); await(locked); assertFalse(lock.validate(p)); assertEquals(0L, lock.tryOptimisticRead()); assertThreadBlocks(t, Thread.State.WAITING); t.interrupt(); awaitTermination(t); assertTrue(lock.isWriteLocked()); }
/** * asReadLock can be locked and unlocked */ public void testAsReadLock() throws Throwable { StampedLock sl = new StampedLock(); Lock lock = sl.asReadLock(); for (Action locker : lockLockers(lock)) { locker.run(); assertTrue(sl.isReadLocked()); assertFalse(sl.isWriteLocked()); assertEquals(1, sl.getReadLockCount()); locker.run(); assertTrue(sl.isReadLocked()); assertEquals(2, sl.getReadLockCount()); lock.unlock(); lock.unlock(); assertUnlocked(sl); } }
/** * asReadWriteLock.readLock can be locked and unlocked */ public void testAsReadWriteLockReadLock() throws Throwable { StampedLock sl = new StampedLock(); Lock lock = sl.asReadWriteLock().readLock(); for (Action locker : lockLockers(lock)) { locker.run(); assertTrue(sl.isReadLocked()); assertFalse(sl.isWriteLocked()); assertEquals(1, sl.getReadLockCount()); locker.run(); assertTrue(sl.isReadLocked()); assertEquals(2, sl.getReadLockCount()); lock.unlock(); lock.unlock(); assertUnlocked(sl); } }
/** * Read locks can be very deeply nested */ public void testDeeplyNestedReadLocks() { final StampedLock lock = new StampedLock(); final int depth = 300; final long[] stamps = new long[depth]; final List<Function<StampedLock, Long>> readLockers = readLockers(); final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers(); for (int i = 0; i < depth; i++) { Function<StampedLock, Long> readLocker = readLockers.get(i % readLockers.size()); long stamp = readLocker.apply(lock); assertEquals(i + 1, lock.getReadLockCount()); assertTrue(lock.isReadLocked()); stamps[i] = stamp; } for (int i = 0; i < depth; i++) { BiConsumer<StampedLock, Long> readUnlocker = readUnlockers.get(i % readUnlockers.size()); assertEquals(depth - i, lock.getReadLockCount()); assertTrue(lock.isReadLocked()); readUnlocker.accept(lock, stamps[depth - 1 - i]); } assertUnlocked(lock); }
static Iterator<Reader> readerIterator(final StampedLock sl, final Phaser gate) { return new Iterator<Reader>() { int i = 0; boolean view = false; public boolean hasNext() { return true; } public Reader next() { switch ((i++)&7) { case 1: case 4: case 7: return reader(sl, gate, view ^= true); case 2: case 5: return interruptibleReader(sl, -1, SECONDS, gate, view ^= true); default: return interruptibleReader(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; }
static Iterator<Writer> writerIterator(final StampedLock sl, final Phaser gate) { return new Iterator<Writer>() { int i = 0; boolean view = false; public boolean hasNext() { return true; } public Writer next() { switch ((i++)&7) { case 1: case 4: case 7: return writer(sl, gate, view ^= true); case 2: case 5: return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true); default: return interruptibleWriter(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; }
public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); StampedLock lock = new StampedLock(); executor.submit(() -> { long stamp = lock.readLock(); try { if (count == 0) { stamp = lock.tryConvertToWriteLock(stamp); if (stamp == 0L) { System.out.println("Could not convert to write lock"); stamp = lock.writeLock(); } count = 23; } System.out.println(count); } finally { lock.unlock(stamp); } }); ConcurrentUtils.stop(executor); }
/** * 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); }
/** * 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); }
/** * 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); }
/** * 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()); }
/** * 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); }