1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  */
  22 
  23 /*
  24  * This file is available under and governed by the GNU General Public
  25  * License version 2 only, as published by the Free Software Foundation.
  26  * However, the following notice accompanied the original version of this
  27  * file:
  28  *
  29  * Written by Doug Lea and Martin Buchholz
  30  * with assistance from members of JCP JSR-166 Expert Group and
  31  * released to the public domain, as explained at
  32  * http://creativecommons.org/publicdomain/zero/1.0/
  33  */
  34 
  35 import static java.util.concurrent.TimeUnit.DAYS;
  36 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  37 
  38 import static java.util.concurrent.locks.StampedLock.isLockStamp;
  39 import static java.util.concurrent.locks.StampedLock.isOptimisticReadStamp;
  40 import static java.util.concurrent.locks.StampedLock.isReadLockStamp;
  41 import static java.util.concurrent.locks.StampedLock.isWriteLockStamp;
  42 
  43 import java.util.ArrayList;
  44 import java.util.List;
  45 import java.util.concurrent.Callable;
  46 import java.util.concurrent.CompletableFuture;
  47 import java.util.concurrent.CountDownLatch;
  48 import java.util.concurrent.Future;
  49 import java.util.concurrent.ThreadLocalRandom;
  50 import java.util.concurrent.TimeUnit;
  51 import java.util.concurrent.atomic.AtomicBoolean;
  52 import java.util.concurrent.locks.Lock;
  53 import java.util.concurrent.locks.StampedLock;
  54 import java.util.function.BiConsumer;
  55 import java.util.function.Consumer;
  56 import java.util.function.Function;
  57 
  58 import junit.framework.Test;
  59 import junit.framework.TestSuite;
  60 
  61 public class StampedLockTest extends JSR166TestCase {
  62     public static void main(String[] args) {
  63         main(suite(), args);
  64     }
  65     public static Test suite() {
  66         return new TestSuite(StampedLockTest.class);
  67     }
  68 
  69     /**
  70      * Releases write lock, checking isWriteLocked before and after
  71      */
  72     void releaseWriteLock(StampedLock lock, long stamp) {
  73         assertTrue(lock.isWriteLocked());
  74         assertValid(lock, stamp);
  75         lock.unlockWrite(stamp);
  76         assertFalse(lock.isWriteLocked());
  77         assertFalse(lock.validate(stamp));
  78     }
  79 
  80     /**
  81      * Releases read lock, checking isReadLocked before and after
  82      */
  83     void releaseReadLock(StampedLock lock, long stamp) {
  84         assertTrue(lock.isReadLocked());
  85         assertValid(lock, stamp);
  86         lock.unlockRead(stamp);
  87         assertFalse(lock.isReadLocked());
  88         assertTrue(lock.validate(stamp));
  89     }
  90 
  91     long assertNonZero(long v) {
  92         assertTrue(v != 0L);
  93         return v;
  94     }
  95 
  96     long assertValid(StampedLock lock, long stamp) {
  97         assertTrue(stamp != 0L);
  98         assertTrue(lock.validate(stamp));
  99         return stamp;
 100     }
 101 
 102     void assertUnlocked(StampedLock lock) {
 103         assertFalse(lock.isReadLocked());
 104         assertFalse(lock.isWriteLocked());
 105         assertEquals(0, lock.getReadLockCount());
 106         assertValid(lock, lock.tryOptimisticRead());
 107     }
 108 
 109     List<Action> lockLockers(Lock lock) {
 110         return List.of(
 111             () -> lock.lock(),
 112             () -> lock.lockInterruptibly(),
 113             () -> lock.tryLock(),
 114             () -> lock.tryLock(Long.MIN_VALUE, DAYS),
 115             () -> lock.tryLock(0L, DAYS),
 116             () -> lock.tryLock(Long.MAX_VALUE, DAYS));
 117     }
 118 
 119     List<Function<StampedLock, Long>> readLockers() {
 120         return List.of(
 121             sl -> sl.readLock(),
 122             sl -> sl.tryReadLock(),
 123             sl -> readLockInterruptiblyUninterrupted(sl),
 124             sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
 125             sl -> tryReadLockUninterrupted(sl, 0L, DAYS),
 126             sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
 127     }
 128 
 129     List<BiConsumer<StampedLock, Long>> readUnlockers() {
 130         return List.of(
 131             (sl, stamp) -> sl.unlockRead(stamp),
 132             (sl, stamp) -> assertTrue(sl.tryUnlockRead()),
 133             (sl, stamp) -> sl.asReadLock().unlock(),
 134             (sl, stamp) -> sl.unlock(stamp),
 135             (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
 136     }
 137 
 138     List<Function<StampedLock, Long>> writeLockers() {
 139         return List.of(
 140             sl -> sl.writeLock(),
 141             sl -> sl.tryWriteLock(),
 142             sl -> writeLockInterruptiblyUninterrupted(sl),
 143             sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS),
 144             sl -> tryWriteLockUninterrupted(sl, 0L, DAYS),
 145             sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
 146     }
 147 
 148     List<BiConsumer<StampedLock, Long>> writeUnlockers() {
 149         return List.of(
 150             (sl, stamp) -> sl.unlockWrite(stamp),
 151             (sl, stamp) -> assertTrue(sl.tryUnlockWrite()),
 152             (sl, stamp) -> sl.asWriteLock().unlock(),
 153             (sl, stamp) -> sl.unlock(stamp),
 154             (sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp)));
 155     }
 156 
 157     /**
 158      * Constructed StampedLock is in unlocked state
 159      */
 160     public void testConstructor() {
 161         assertUnlocked(new StampedLock());
 162     }
 163 
 164     /**
 165      * write-locking, then unlocking, an unlocked lock succeed
 166      */
 167     public void testWriteLock_lockUnlock() {
 168         StampedLock lock = new StampedLock();
 169 
 170         for (Function<StampedLock, Long> writeLocker : writeLockers())
 171         for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
 172             assertFalse(lock.isWriteLocked());
 173             assertFalse(lock.isReadLocked());
 174             assertEquals(0, lock.getReadLockCount());
 175 
 176             long s = writeLocker.apply(lock);
 177             assertValid(lock, s);
 178             assertTrue(lock.isWriteLocked());
 179             assertFalse(lock.isReadLocked());
 180             assertEquals(0, lock.getReadLockCount());
 181             writeUnlocker.accept(lock, s);
 182             assertUnlocked(lock);
 183         }
 184     }
 185 
 186     /**
 187      * read-locking, then unlocking, an unlocked lock succeed
 188      */
 189     public void testReadLock_lockUnlock() {
 190         StampedLock lock = new StampedLock();
 191 
 192         for (Function<StampedLock, Long> readLocker : readLockers())
 193         for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
 194             long s = 42;
 195             for (int i = 0; i < 2; i++) {
 196                 s = assertValid(lock, readLocker.apply(lock));
 197                 assertFalse(lock.isWriteLocked());
 198                 assertTrue(lock.isReadLocked());
 199                 assertEquals(i + 1, lock.getReadLockCount());
 200             }
 201             for (int i = 0; i < 2; i++) {
 202                 assertFalse(lock.isWriteLocked());
 203                 assertTrue(lock.isReadLocked());
 204                 assertEquals(2 - i, lock.getReadLockCount());
 205                 readUnlocker.accept(lock, s);
 206             }
 207             assertUnlocked(lock);
 208         }
 209     }
 210 
 211     /**
 212      * tryUnlockWrite fails if not write locked
 213      */
 214     public void testTryUnlockWrite_failure() {
 215         StampedLock lock = new StampedLock();
 216         assertFalse(lock.tryUnlockWrite());
 217 
 218         for (Function<StampedLock, Long> readLocker : readLockers())
 219         for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
 220             long s = assertValid(lock, readLocker.apply(lock));
 221             assertFalse(lock.tryUnlockWrite());
 222             assertTrue(lock.isReadLocked());
 223             readUnlocker.accept(lock, s);
 224             assertUnlocked(lock);
 225         }
 226     }
 227 
 228     /**
 229      * tryUnlockRead fails if not read locked
 230      */
 231     public void testTryUnlockRead_failure() {
 232         StampedLock lock = new StampedLock();
 233         assertFalse(lock.tryUnlockRead());
 234 
 235         for (Function<StampedLock, Long> writeLocker : writeLockers())
 236         for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
 237             long s = writeLocker.apply(lock);
 238             assertFalse(lock.tryUnlockRead());
 239             assertTrue(lock.isWriteLocked());
 240             writeUnlocker.accept(lock, s);
 241             assertUnlocked(lock);
 242         }
 243     }
 244 
 245     /**
 246      * validate(0L) fails
 247      */
 248     public void testValidate0() {
 249         StampedLock lock = new StampedLock();
 250         assertFalse(lock.validate(0L));
 251     }
 252 
 253     /**
 254      * A stamp obtained from a successful lock operation validates while the lock is held
 255      */
 256     public void testValidate() throws InterruptedException {
 257         StampedLock lock = new StampedLock();
 258 
 259         for (Function<StampedLock, Long> readLocker : readLockers())
 260         for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
 261             long s = assertNonZero(readLocker.apply(lock));
 262             assertTrue(lock.validate(s));
 263             readUnlocker.accept(lock, s);
 264         }
 265 
 266         for (Function<StampedLock, Long> writeLocker : writeLockers())
 267         for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
 268             long s = assertNonZero(writeLocker.apply(lock));
 269             assertTrue(lock.validate(s));
 270             writeUnlocker.accept(lock, s);
 271         }
 272     }
 273 
 274     /**
 275      * A stamp obtained from an unsuccessful lock operation does not validate
 276      */
 277     public void testValidate2() throws InterruptedException {
 278         StampedLock lock = new StampedLock();
 279         long s = assertNonZero(lock.writeLock());
 280         assertTrue(lock.validate(s));
 281         assertFalse(lock.validate(lock.tryWriteLock()));
 282         assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
 283                                                     randomTimeUnit())));
 284         assertFalse(lock.validate(lock.tryReadLock()));
 285         assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
 286                                                     randomTimeUnit())));
 287         assertFalse(lock.validate(lock.tryOptimisticRead()));
 288         lock.unlockWrite(s);
 289     }
 290 
 291     void assertThrowInterruptedExceptionWhenPreInterrupted(Action[] actions) {
 292         for (Action action : actions) {
 293             Thread.currentThread().interrupt();
 294             try {
 295                 action.run();
 296                 shouldThrow();
 297             }
 298             catch (InterruptedException success) {}
 299             catch (Throwable fail) { threadUnexpectedException(fail); }
 300             assertFalse(Thread.interrupted());
 301         }
 302     }
 303 
 304     /**
 305      * interruptible operations throw InterruptedException when pre-interrupted
 306      */
 307     public void testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted() {
 308         final StampedLock lock = new StampedLock();
 309 
 310         Action[] interruptibleLockActions = {
 311             () -> lock.writeLockInterruptibly(),
 312             () -> lock.tryWriteLock(Long.MIN_VALUE, DAYS),
 313             () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
 314             () -> lock.readLockInterruptibly(),
 315             () -> lock.tryReadLock(Long.MIN_VALUE, DAYS),
 316             () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
 317             () -> lock.asWriteLock().lockInterruptibly(),
 318             () -> lock.asWriteLock().tryLock(0L, DAYS),
 319             () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
 320             () -> lock.asReadLock().lockInterruptibly(),
 321             () -> lock.asReadLock().tryLock(0L, DAYS),
 322             () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
 323         };
 324         shuffle(interruptibleLockActions);
 325 
 326         assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
 327         {
 328             long s = lock.writeLock();
 329             assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
 330             lock.unlockWrite(s);
 331         }
 332         {
 333             long s = lock.readLock();
 334             assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions);
 335             lock.unlockRead(s);
 336         }
 337     }
 338 
 339     void assertThrowInterruptedExceptionWhenInterrupted(Action[] actions) {
 340         int n = actions.length;
 341         Future<?>[] futures = new Future<?>[n];
 342         CountDownLatch threadsStarted = new CountDownLatch(n);
 343         CountDownLatch done = new CountDownLatch(n);
 344 
 345         for (int i = 0; i < n; i++) {
 346             Action action = actions[i];
 347             futures[i] = cachedThreadPool.submit(new CheckedRunnable() {
 348                 public void realRun() throws Throwable {
 349                     threadsStarted.countDown();
 350                     try {
 351                         action.run();
 352                         shouldThrow();
 353                     }
 354                     catch (InterruptedException success) {}
 355                     catch (Throwable fail) { threadUnexpectedException(fail); }
 356                     assertFalse(Thread.interrupted());
 357                     done.countDown();
 358                 }});
 359         }
 360 
 361         await(threadsStarted);
 362         assertEquals(n, done.getCount());
 363         for (Future<?> future : futures) // Interrupt all the tasks
 364             future.cancel(true);
 365         await(done);
 366     }
 367 
 368     /**
 369      * interruptible operations throw InterruptedException when write locked and interrupted
 370      */
 371     public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() {
 372         final StampedLock lock = new StampedLock();
 373         long stamp = lock.writeLock();
 374 
 375         Action[] interruptibleLockBlockingActions = {
 376             () -> lock.writeLockInterruptibly(),
 377             () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
 378             () -> lock.readLockInterruptibly(),
 379             () -> lock.tryReadLock(Long.MAX_VALUE, DAYS),
 380             () -> lock.asWriteLock().lockInterruptibly(),
 381             () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
 382             () -> lock.asReadLock().lockInterruptibly(),
 383             () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS),
 384         };
 385         shuffle(interruptibleLockBlockingActions);
 386 
 387         assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
 388 
 389         releaseWriteLock(lock, stamp);
 390     }
 391 
 392     /**
 393      * interruptible operations throw InterruptedException when read locked and interrupted
 394      */
 395     public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() {
 396         final StampedLock lock = new StampedLock();
 397         long stamp = lock.readLock();
 398 
 399         Action[] interruptibleLockBlockingActions = {
 400             () -> lock.writeLockInterruptibly(),
 401             () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS),
 402             () -> lock.asWriteLock().lockInterruptibly(),
 403             () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS),
 404         };
 405         shuffle(interruptibleLockBlockingActions);
 406 
 407         assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions);
 408 
 409         releaseReadLock(lock, stamp);
 410     }
 411 
 412     /**
 413      * Non-interruptible operations ignore and preserve interrupt status
 414      */
 415     public void testNonInterruptibleOperationsIgnoreInterrupts() {
 416         final StampedLock lock = new StampedLock();
 417         Thread.currentThread().interrupt();
 418 
 419         for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
 420             long s = assertValid(lock, lock.readLock());
 421             readUnlocker.accept(lock, s);
 422             s = assertValid(lock, lock.tryReadLock());
 423             readUnlocker.accept(lock, s);
 424         }
 425 
 426         lock.asReadLock().lock();
 427         lock.asReadLock().unlock();
 428 
 429         for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
 430             long s = assertValid(lock, lock.writeLock());
 431             writeUnlocker.accept(lock, s);
 432             s = assertValid(lock, lock.tryWriteLock());
 433             writeUnlocker.accept(lock, s);
 434         }
 435 
 436         lock.asWriteLock().lock();
 437         lock.asWriteLock().unlock();
 438 
 439         assertTrue(Thread.interrupted());
 440     }
 441 
 442     /**
 443      * tryWriteLock on an unlocked lock succeeds
 444      */
 445     public void testTryWriteLock() {
 446         final StampedLock lock = new StampedLock();
 447         long s = lock.tryWriteLock();
 448         assertTrue(s != 0L);
 449         assertTrue(lock.isWriteLocked());
 450         assertEquals(0L, lock.tryWriteLock());
 451         releaseWriteLock(lock, s);
 452     }
 453 
 454     /**
 455      * tryWriteLock fails if locked
 456      */
 457     public void testTryWriteLockWhenLocked() {
 458         final StampedLock lock = new StampedLock();
 459         long s = lock.writeLock();
 460         Thread t = newStartedThread(new CheckedRunnable() {
 461             public void realRun() {
 462                 assertEquals(0L, lock.tryWriteLock());
 463             }});
 464 
 465         assertEquals(0L, lock.tryWriteLock());
 466         awaitTermination(t);
 467         releaseWriteLock(lock, s);
 468     }
 469 
 470     /**
 471      * tryReadLock fails if write-locked
 472      */
 473     public void testTryReadLockWhenLocked() {
 474         final StampedLock lock = new StampedLock();
 475         long s = lock.writeLock();
 476         Thread t = newStartedThread(new CheckedRunnable() {
 477             public void realRun() {
 478                 assertEquals(0L, lock.tryReadLock());
 479             }});
 480 
 481         assertEquals(0L, lock.tryReadLock());
 482         awaitTermination(t);
 483         releaseWriteLock(lock, s);
 484     }
 485 
 486     /**
 487      * Multiple threads can hold a read lock when not write-locked
 488      */
 489     public void testMultipleReadLocks() {
 490         final StampedLock lock = new StampedLock();
 491         final long s = lock.readLock();
 492         Thread t = newStartedThread(new CheckedRunnable() {
 493             public void realRun() throws InterruptedException {
 494                 long s2 = lock.tryReadLock();
 495                 assertValid(lock, s2);
 496                 lock.unlockRead(s2);
 497                 long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS);
 498                 assertValid(lock, s3);
 499                 lock.unlockRead(s3);
 500                 long s4 = lock.readLock();
 501                 assertValid(lock, s4);
 502                 lock.unlockRead(s4);
 503                 lock.asReadLock().lock();
 504                 lock.asReadLock().unlock();
 505                 lock.asReadLock().lockInterruptibly();
 506                 lock.asReadLock().unlock();
 507                 lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS);
 508                 lock.asReadLock().unlock();
 509             }});
 510 
 511         awaitTermination(t);
 512         lock.unlockRead(s);
 513     }
 514 
 515     /**
 516      * writeLock() succeeds only after a reading thread unlocks
 517      */
 518     public void testWriteAfterReadLock() throws InterruptedException {
 519         final CountDownLatch aboutToLock = new CountDownLatch(1);
 520         final StampedLock lock = new StampedLock();
 521         long rs = lock.readLock();
 522         Thread t = newStartedThread(new CheckedRunnable() {
 523             public void realRun() {
 524                 aboutToLock.countDown();
 525                 long s = lock.writeLock();
 526                 assertTrue(lock.isWriteLocked());
 527                 assertFalse(lock.isReadLocked());
 528                 lock.unlockWrite(s);
 529             }});
 530 
 531         await(aboutToLock);
 532         assertThreadBlocks(t, Thread.State.WAITING);
 533         assertFalse(lock.isWriteLocked());
 534         assertTrue(lock.isReadLocked());
 535         lock.unlockRead(rs);
 536         awaitTermination(t);
 537         assertUnlocked(lock);
 538     }
 539 
 540     /**
 541      * writeLock() succeeds only after reading threads unlock
 542      */
 543     public void testWriteAfterMultipleReadLocks() {
 544         final StampedLock lock = new StampedLock();
 545         long s = lock.readLock();
 546         Thread t1 = newStartedThread(new CheckedRunnable() {
 547             public void realRun() {
 548                 long rs = lock.readLock();
 549                 lock.unlockRead(rs);
 550             }});
 551 
 552         awaitTermination(t1);
 553 
 554         Thread t2 = newStartedThread(new CheckedRunnable() {
 555             public void realRun() {
 556                 long ws = lock.writeLock();
 557                 lock.unlockWrite(ws);
 558             }});
 559 
 560         assertTrue(lock.isReadLocked());
 561         assertFalse(lock.isWriteLocked());
 562         lock.unlockRead(s);
 563         awaitTermination(t2);
 564         assertUnlocked(lock);
 565     }
 566 
 567     /**
 568      * readLock() succeed only after a writing thread unlocks
 569      */
 570     public void testReadAfterWriteLock() {
 571         final StampedLock lock = new StampedLock();
 572         final CountDownLatch threadsStarted = new CountDownLatch(2);
 573         final long s = lock.writeLock();
 574         final Runnable acquireReleaseReadLock = new CheckedRunnable() {
 575             public void realRun() {
 576                 threadsStarted.countDown();
 577                 long rs = lock.readLock();
 578                 assertTrue(lock.isReadLocked());
 579                 assertFalse(lock.isWriteLocked());
 580                 lock.unlockRead(rs);
 581             }};
 582         Thread t1 = newStartedThread(acquireReleaseReadLock);
 583         Thread t2 = newStartedThread(acquireReleaseReadLock);
 584 
 585         await(threadsStarted);
 586         assertThreadBlocks(t1, Thread.State.WAITING);
 587         assertThreadBlocks(t2, Thread.State.WAITING);
 588         assertTrue(lock.isWriteLocked());
 589         assertFalse(lock.isReadLocked());
 590         releaseWriteLock(lock, s);
 591         awaitTermination(t1);
 592         awaitTermination(t2);
 593         assertUnlocked(lock);
 594     }
 595 
 596     /**
 597      * tryReadLock succeeds if read locked but not write locked
 598      */
 599     public void testTryLockWhenReadLocked() {
 600         final StampedLock lock = new StampedLock();
 601         long s = lock.readLock();
 602         Thread t = newStartedThread(new CheckedRunnable() {
 603             public void realRun() {
 604                 long rs = lock.tryReadLock();
 605                 assertValid(lock, rs);
 606                 lock.unlockRead(rs);
 607             }});
 608 
 609         awaitTermination(t);
 610         lock.unlockRead(s);
 611     }
 612 
 613     /**
 614      * tryWriteLock fails when read locked
 615      */
 616     public void testTryWriteLockWhenReadLocked() {
 617         final StampedLock lock = new StampedLock();
 618         long s = lock.readLock();
 619         Thread t = newStartedThread(new CheckedRunnable() {
 620             public void realRun() {
 621                 assertEquals(0L, lock.tryWriteLock());
 622             }});
 623 
 624         awaitTermination(t);
 625         lock.unlockRead(s);
 626     }
 627 
 628     /**
 629      * timed lock operations time out if lock not available
 630      */
 631     public void testTimedLock_Timeout() throws Exception {
 632         ArrayList<Future<?>> futures = new ArrayList<>();
 633 
 634         // Write locked
 635         final StampedLock lock = new StampedLock();
 636         long stamp = lock.writeLock();
 637         assertEquals(0L, lock.tryReadLock(0L, DAYS));
 638         assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS));
 639         assertFalse(lock.asReadLock().tryLock(0L, DAYS));
 640         assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS));
 641         assertEquals(0L, lock.tryWriteLock(0L, DAYS));
 642         assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS));
 643         assertFalse(lock.asWriteLock().tryLock(0L, DAYS));
 644         assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
 645 
 646         futures.add(cachedThreadPool.submit(new CheckedRunnable() {
 647             public void realRun() throws InterruptedException {
 648                 long startTime = System.nanoTime();
 649                 assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS));
 650                 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 651             }}));
 652 
 653         futures.add(cachedThreadPool.submit(new CheckedRunnable() {
 654             public void realRun() throws InterruptedException {
 655                 long startTime = System.nanoTime();
 656                 assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS));
 657                 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 658             }}));
 659 
 660         // Read locked
 661         final StampedLock lock2 = new StampedLock();
 662         long stamp2 = lock2.readLock();
 663         assertEquals(0L, lock2.tryWriteLock(0L, DAYS));
 664         assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS));
 665         assertFalse(lock2.asWriteLock().tryLock(0L, DAYS));
 666         assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS));
 667 
 668         futures.add(cachedThreadPool.submit(new CheckedRunnable() {
 669             public void realRun() throws InterruptedException {
 670                 long startTime = System.nanoTime();
 671                 assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS));
 672                 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 673             }}));
 674 
 675         for (Future<?> future : futures)
 676             assertNull(future.get());
 677 
 678         releaseWriteLock(lock, stamp);
 679         releaseReadLock(lock2, stamp2);
 680     }
 681 
 682     /**
 683      * writeLockInterruptibly succeeds if unlocked
 684      */
 685     public void testWriteLockInterruptibly() throws InterruptedException {
 686         final StampedLock lock = new StampedLock();
 687         long s = lock.writeLockInterruptibly();
 688         assertTrue(lock.isWriteLocked());
 689         releaseWriteLock(lock, s);
 690     }
 691 
 692     /**
 693      * readLockInterruptibly succeeds if lock free
 694      */
 695     public void testReadLockInterruptibly() throws InterruptedException {
 696         final StampedLock lock = new StampedLock();
 697 
 698         long s = assertValid(lock, lock.readLockInterruptibly());
 699         assertTrue(lock.isReadLocked());
 700         lock.unlockRead(s);
 701 
 702         lock.asReadLock().lockInterruptibly();
 703         assertTrue(lock.isReadLocked());
 704         lock.asReadLock().unlock();
 705     }
 706 
 707     /**
 708      * A serialized lock deserializes as unlocked
 709      */
 710     public void testSerialization() {
 711         StampedLock lock = new StampedLock();
 712         lock.writeLock();
 713         StampedLock clone = serialClone(lock);
 714         assertTrue(lock.isWriteLocked());
 715         assertFalse(clone.isWriteLocked());
 716         long s = clone.writeLock();
 717         assertTrue(clone.isWriteLocked());
 718         clone.unlockWrite(s);
 719         assertFalse(clone.isWriteLocked());
 720     }
 721 
 722     /**
 723      * toString indicates current lock state
 724      */
 725     public void testToString() {
 726         StampedLock lock = new StampedLock();
 727         assertTrue(lock.toString().contains("Unlocked"));
 728         long s = lock.writeLock();
 729         assertTrue(lock.toString().contains("Write-locked"));
 730         lock.unlockWrite(s);
 731         s = lock.readLock();
 732         assertTrue(lock.toString().contains("Read-locks"));
 733         releaseReadLock(lock, s);
 734     }
 735 
 736     /**
 737      * tryOptimisticRead succeeds and validates if unlocked, fails if
 738      * exclusively locked
 739      */
 740     public void testValidateOptimistic() throws InterruptedException {
 741         StampedLock lock = new StampedLock();
 742 
 743         assertValid(lock, lock.tryOptimisticRead());
 744 
 745         for (Function<StampedLock, Long> writeLocker : writeLockers()) {
 746             long s = assertValid(lock, writeLocker.apply(lock));
 747             assertEquals(0L, lock.tryOptimisticRead());
 748             releaseWriteLock(lock, s);
 749         }
 750 
 751         for (Function<StampedLock, Long> readLocker : readLockers()) {
 752             long s = assertValid(lock, readLocker.apply(lock));
 753             long p = assertValid(lock, lock.tryOptimisticRead());
 754             releaseReadLock(lock, s);
 755             assertTrue(lock.validate(p));
 756         }
 757 
 758         assertValid(lock, lock.tryOptimisticRead());
 759     }
 760 
 761     /**
 762      * tryOptimisticRead stamp does not validate if a write lock intervenes
 763      */
 764     public void testValidateOptimisticWriteLocked() {
 765         final StampedLock lock = new StampedLock();
 766         final long p = assertValid(lock, lock.tryOptimisticRead());
 767         final long s = assertValid(lock, lock.writeLock());
 768         assertFalse(lock.validate(p));
 769         assertEquals(0L, lock.tryOptimisticRead());
 770         assertTrue(lock.validate(s));
 771         lock.unlockWrite(s);
 772     }
 773 
 774     /**
 775      * tryOptimisticRead stamp does not validate if a write lock
 776      * intervenes in another thread
 777      */
 778     public void testValidateOptimisticWriteLocked2()
 779             throws InterruptedException {
 780         final CountDownLatch locked = new CountDownLatch(1);
 781         final StampedLock lock = new StampedLock();
 782         final long p = assertValid(lock, lock.tryOptimisticRead());
 783 
 784         Thread t = newStartedThread(new CheckedInterruptedRunnable() {
 785             public void realRun() throws InterruptedException {
 786                 lock.writeLockInterruptibly();
 787                 locked.countDown();
 788                 lock.writeLockInterruptibly();
 789             }});
 790 
 791         await(locked);
 792         assertFalse(lock.validate(p));
 793         assertEquals(0L, lock.tryOptimisticRead());
 794         assertThreadBlocks(t, Thread.State.WAITING);
 795         t.interrupt();
 796         awaitTermination(t);
 797         assertTrue(lock.isWriteLocked());
 798     }
 799 
 800     /**
 801      * tryConvertToOptimisticRead succeeds and validates if successfully locked
 802      */
 803     public void testTryConvertToOptimisticRead() throws InterruptedException {
 804         StampedLock lock = new StampedLock();
 805         long s, p, q;
 806         assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
 807 
 808         s = assertValid(lock, lock.tryOptimisticRead());
 809         assertEquals(s, lock.tryConvertToOptimisticRead(s));
 810         assertTrue(lock.validate(s));
 811 
 812         for (Function<StampedLock, Long> writeLocker : writeLockers()) {
 813             s = assertValid(lock, writeLocker.apply(lock));
 814             p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
 815             assertFalse(lock.validate(s));
 816             assertTrue(lock.validate(p));
 817             assertUnlocked(lock);
 818         }
 819 
 820         for (Function<StampedLock, Long> readLocker : readLockers()) {
 821             s = assertValid(lock, readLocker.apply(lock));
 822             q = assertValid(lock, lock.tryOptimisticRead());
 823             assertEquals(q, lock.tryConvertToOptimisticRead(q));
 824             assertTrue(lock.validate(q));
 825             assertTrue(lock.isReadLocked());
 826             p = assertValid(lock, lock.tryConvertToOptimisticRead(s));
 827             assertTrue(lock.validate(p));
 828             assertTrue(lock.validate(s));
 829             assertUnlocked(lock);
 830             assertEquals(q, lock.tryConvertToOptimisticRead(q));
 831             assertTrue(lock.validate(q));
 832         }
 833     }
 834 
 835     /**
 836      * tryConvertToReadLock succeeds for valid stamps
 837      */
 838     public void testTryConvertToReadLock() throws InterruptedException {
 839         StampedLock lock = new StampedLock();
 840         long s, p;
 841 
 842         assertEquals(0L, lock.tryConvertToReadLock(0L));
 843 
 844         s = assertValid(lock, lock.tryOptimisticRead());
 845         p = assertValid(lock, lock.tryConvertToReadLock(s));
 846         assertTrue(lock.isReadLocked());
 847         assertEquals(1, lock.getReadLockCount());
 848         assertTrue(lock.validate(s));
 849         lock.unlockRead(p);
 850 
 851         s = assertValid(lock, lock.tryOptimisticRead());
 852         lock.readLock();
 853         p = assertValid(lock, lock.tryConvertToReadLock(s));
 854         assertTrue(lock.isReadLocked());
 855         assertEquals(2, lock.getReadLockCount());
 856         lock.unlockRead(p);
 857         lock.unlockRead(p);
 858         assertUnlocked(lock);
 859 
 860         for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
 861             for (Function<StampedLock, Long> writeLocker : writeLockers()) {
 862                 s = assertValid(lock, writeLocker.apply(lock));
 863                 p = assertValid(lock, lock.tryConvertToReadLock(s));
 864                 assertFalse(lock.validate(s));
 865                 assertTrue(lock.isReadLocked());
 866                 assertEquals(1, lock.getReadLockCount());
 867                 readUnlocker.accept(lock, p);
 868             }
 869 
 870             for (Function<StampedLock, Long> readLocker : readLockers()) {
 871                 s = assertValid(lock, readLocker.apply(lock));
 872                 assertEquals(s, lock.tryConvertToReadLock(s));
 873                 assertTrue(lock.validate(s));
 874                 assertTrue(lock.isReadLocked());
 875                 assertEquals(1, lock.getReadLockCount());
 876                 readUnlocker.accept(lock, s);
 877             }
 878         }
 879     }
 880 
 881     /**
 882      * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked
 883      */
 884     public void testTryConvertToWriteLock() throws InterruptedException {
 885         StampedLock lock = new StampedLock();
 886         long s, p;
 887 
 888         assertEquals(0L, lock.tryConvertToWriteLock(0L));
 889 
 890         assertTrue((s = lock.tryOptimisticRead()) != 0L);
 891         assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
 892         assertTrue(lock.isWriteLocked());
 893         lock.unlockWrite(p);
 894 
 895         for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
 896             for (Function<StampedLock, Long> writeLocker : writeLockers()) {
 897                 s = assertValid(lock, writeLocker.apply(lock));
 898                 assertEquals(s, lock.tryConvertToWriteLock(s));
 899                 assertTrue(lock.validate(s));
 900                 assertTrue(lock.isWriteLocked());
 901                 writeUnlocker.accept(lock, s);
 902             }
 903 
 904             for (Function<StampedLock, Long> readLocker : readLockers()) {
 905                 s = assertValid(lock, readLocker.apply(lock));
 906                 p = assertValid(lock, lock.tryConvertToWriteLock(s));
 907                 assertFalse(lock.validate(s));
 908                 assertTrue(lock.validate(p));
 909                 assertTrue(lock.isWriteLocked());
 910                 writeUnlocker.accept(lock, p);
 911             }
 912         }
 913 
 914         // failure if multiply read locked
 915         for (Function<StampedLock, Long> readLocker : readLockers()) {
 916             s = assertValid(lock, readLocker.apply(lock));
 917             p = assertValid(lock, readLocker.apply(lock));
 918             assertEquals(0L, lock.tryConvertToWriteLock(s));
 919             assertTrue(lock.validate(s));
 920             assertTrue(lock.validate(p));
 921             assertEquals(2, lock.getReadLockCount());
 922             lock.unlock(p);
 923             lock.unlock(s);
 924             assertUnlocked(lock);
 925         }
 926     }
 927 
 928     /**
 929      * asWriteLock can be locked and unlocked
 930      */
 931     public void testAsWriteLock() throws Throwable {
 932         StampedLock sl = new StampedLock();
 933         Lock lock = sl.asWriteLock();
 934         for (Action locker : lockLockers(lock)) {
 935             locker.run();
 936             assertTrue(sl.isWriteLocked());
 937             assertFalse(sl.isReadLocked());
 938             assertFalse(lock.tryLock());
 939             lock.unlock();
 940             assertUnlocked(sl);
 941         }
 942     }
 943 
 944     /**
 945      * asReadLock can be locked and unlocked
 946      */
 947     public void testAsReadLock() throws Throwable {
 948         StampedLock sl = new StampedLock();
 949         Lock lock = sl.asReadLock();
 950         for (Action locker : lockLockers(lock)) {
 951             locker.run();
 952             assertTrue(sl.isReadLocked());
 953             assertFalse(sl.isWriteLocked());
 954             assertEquals(1, sl.getReadLockCount());
 955             locker.run();
 956             assertTrue(sl.isReadLocked());
 957             assertEquals(2, sl.getReadLockCount());
 958             lock.unlock();
 959             lock.unlock();
 960             assertUnlocked(sl);
 961         }
 962     }
 963 
 964     /**
 965      * asReadWriteLock.writeLock can be locked and unlocked
 966      */
 967     public void testAsReadWriteLockWriteLock() throws Throwable {
 968         StampedLock sl = new StampedLock();
 969         Lock lock = sl.asReadWriteLock().writeLock();
 970         for (Action locker : lockLockers(lock)) {
 971             locker.run();
 972             assertTrue(sl.isWriteLocked());
 973             assertFalse(sl.isReadLocked());
 974             assertFalse(lock.tryLock());
 975             lock.unlock();
 976             assertUnlocked(sl);
 977         }
 978     }
 979 
 980     /**
 981      * asReadWriteLock.readLock can be locked and unlocked
 982      */
 983     public void testAsReadWriteLockReadLock() throws Throwable {
 984         StampedLock sl = new StampedLock();
 985         Lock lock = sl.asReadWriteLock().readLock();
 986         for (Action locker : lockLockers(lock)) {
 987             locker.run();
 988             assertTrue(sl.isReadLocked());
 989             assertFalse(sl.isWriteLocked());
 990             assertEquals(1, sl.getReadLockCount());
 991             locker.run();
 992             assertTrue(sl.isReadLocked());
 993             assertEquals(2, sl.getReadLockCount());
 994             lock.unlock();
 995             lock.unlock();
 996             assertUnlocked(sl);
 997         }
 998     }
 999 
1000     /**
1001      * Lock.newCondition throws UnsupportedOperationException
1002      */
1003     public void testLockViewsDoNotSupportConditions() {
1004         StampedLock sl = new StampedLock();
1005         assertThrows(UnsupportedOperationException.class,
1006                      () -> sl.asWriteLock().newCondition(),
1007                      () -> sl.asReadLock().newCondition(),
1008                      () -> sl.asReadWriteLock().writeLock().newCondition(),
1009                      () -> sl.asReadWriteLock().readLock().newCondition());
1010     }
1011 
1012     /**
1013      * Passing optimistic read stamps to unlock operations result in
1014      * IllegalMonitorStateException
1015      */
1016     public void testCannotUnlockOptimisticReadStamps() {
1017         {
1018             StampedLock sl = new StampedLock();
1019             long stamp = assertValid(sl, sl.tryOptimisticRead());
1020             assertThrows(IllegalMonitorStateException.class,
1021                 () -> sl.unlockRead(stamp));
1022         }
1023         {
1024             StampedLock sl = new StampedLock();
1025             long stamp = sl.tryOptimisticRead();
1026             assertThrows(IllegalMonitorStateException.class,
1027                 () -> sl.unlock(stamp));
1028         }
1029 
1030         {
1031             StampedLock sl = new StampedLock();
1032             long stamp = sl.tryOptimisticRead();
1033             sl.writeLock();
1034             assertThrows(IllegalMonitorStateException.class,
1035                 () -> sl.unlock(stamp));
1036         }
1037         {
1038             StampedLock sl = new StampedLock();
1039             sl.readLock();
1040             long stamp = assertValid(sl, sl.tryOptimisticRead());
1041             assertThrows(IllegalMonitorStateException.class,
1042                 () -> sl.unlockRead(stamp));
1043         }
1044         {
1045             StampedLock sl = new StampedLock();
1046             sl.readLock();
1047             long stamp = assertValid(sl, sl.tryOptimisticRead());
1048             assertThrows(IllegalMonitorStateException.class,
1049                 () -> sl.unlock(stamp));
1050         }
1051 
1052         {
1053             StampedLock sl = new StampedLock();
1054             long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1055             assertValid(sl, stamp);
1056             sl.writeLock();
1057             assertThrows(IllegalMonitorStateException.class,
1058                 () -> sl.unlockWrite(stamp));
1059         }
1060         {
1061             StampedLock sl = new StampedLock();
1062             long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1063             sl.writeLock();
1064             assertThrows(IllegalMonitorStateException.class,
1065                 () -> sl.unlock(stamp));
1066         }
1067         {
1068             StampedLock sl = new StampedLock();
1069             long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1070             sl.readLock();
1071             assertThrows(IllegalMonitorStateException.class,
1072                 () -> sl.unlockRead(stamp));
1073         }
1074         {
1075             StampedLock sl = new StampedLock();
1076             long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
1077             sl.readLock();
1078             assertThrows(IllegalMonitorStateException.class,
1079                 () -> sl.unlock(stamp));
1080         }
1081 
1082         {
1083             StampedLock sl = new StampedLock();
1084             long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1085             assertValid(sl, stamp);
1086             sl.writeLock();
1087             assertThrows(IllegalMonitorStateException.class,
1088                 () -> sl.unlockWrite(stamp));
1089             }
1090         {
1091             StampedLock sl = new StampedLock();
1092             long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1093             sl.writeLock();
1094             assertThrows(IllegalMonitorStateException.class,
1095                 () -> sl.unlock(stamp));
1096         }
1097         {
1098             StampedLock sl = new StampedLock();
1099             long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1100             sl.readLock();
1101             assertThrows(IllegalMonitorStateException.class,
1102                 () -> sl.unlockRead(stamp));
1103         }
1104         {
1105             StampedLock sl = new StampedLock();
1106             sl.readLock();
1107             long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1108             assertValid(sl, stamp);
1109             sl.readLock();
1110             assertThrows(IllegalMonitorStateException.class,
1111                 () -> sl.unlockRead(stamp));
1112         }
1113         {
1114             StampedLock sl = new StampedLock();
1115             long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1116             sl.readLock();
1117             assertThrows(IllegalMonitorStateException.class,
1118                 () -> sl.unlock(stamp));
1119         }
1120         {
1121             StampedLock sl = new StampedLock();
1122             sl.readLock();
1123             long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
1124             sl.readLock();
1125             assertThrows(IllegalMonitorStateException.class,
1126                 () -> sl.unlock(stamp));
1127         }
1128     }
1129 
1130     static long writeLockInterruptiblyUninterrupted(StampedLock sl) {
1131         try { return sl.writeLockInterruptibly(); }
1132         catch (InterruptedException ex) { throw new AssertionError(ex); }
1133     }
1134 
1135     static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1136         try { return sl.tryWriteLock(time, unit); }
1137         catch (InterruptedException ex) { throw new AssertionError(ex); }
1138     }
1139 
1140     static long readLockInterruptiblyUninterrupted(StampedLock sl) {
1141         try { return sl.readLockInterruptibly(); }
1142         catch (InterruptedException ex) { throw new AssertionError(ex); }
1143     }
1144 
1145     static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) {
1146         try { return sl.tryReadLock(time, unit); }
1147         catch (InterruptedException ex) { throw new AssertionError(ex); }
1148     }
1149 
1150     /**
1151      * Invalid stamps result in IllegalMonitorStateException
1152      */
1153     public void testInvalidStampsThrowIllegalMonitorStateException() {
1154         final StampedLock sl = new StampedLock();
1155 
1156         assertThrows(IllegalMonitorStateException.class,
1157                      () -> sl.unlockWrite(0L),
1158                      () -> sl.unlockRead(0L),
1159                      () -> sl.unlock(0L));
1160 
1161         final long optimisticStamp = sl.tryOptimisticRead();
1162         final long readStamp = sl.readLock();
1163         sl.unlockRead(readStamp);
1164         final long writeStamp = sl.writeLock();
1165         sl.unlockWrite(writeStamp);
1166         assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L);
1167         final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp };
1168         final Runnable assertNoLongerValidStampsThrow = () -> {
1169             for (long noLongerValidStamp : noLongerValidStamps)
1170                 assertThrows(IllegalMonitorStateException.class,
1171                              () -> sl.unlockWrite(noLongerValidStamp),
1172                              () -> sl.unlockRead(noLongerValidStamp),
1173                              () -> sl.unlock(noLongerValidStamp));
1174         };
1175         assertNoLongerValidStampsThrow.run();
1176 
1177         for (Function<StampedLock, Long> readLocker : readLockers())
1178         for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) {
1179             final long stamp = readLocker.apply(sl);
1180             assertValid(sl, stamp);
1181             assertNoLongerValidStampsThrow.run();
1182             assertThrows(IllegalMonitorStateException.class,
1183                          () -> sl.unlockWrite(stamp),
1184                          () -> sl.unlockRead(sl.tryOptimisticRead()),
1185                          () -> sl.unlockRead(0L));
1186             readUnlocker.accept(sl, stamp);
1187             assertUnlocked(sl);
1188             assertNoLongerValidStampsThrow.run();
1189         }
1190 
1191         for (Function<StampedLock, Long> writeLocker : writeLockers())
1192         for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1193             final long stamp = writeLocker.apply(sl);
1194             assertValid(sl, stamp);
1195             assertNoLongerValidStampsThrow.run();
1196             assertThrows(IllegalMonitorStateException.class,
1197                          () -> sl.unlockRead(stamp),
1198                          () -> sl.unlockWrite(0L));
1199             writeUnlocker.accept(sl, stamp);
1200             assertUnlocked(sl);
1201             assertNoLongerValidStampsThrow.run();
1202         }
1203     }
1204 
1205     /**
1206      * Read locks can be very deeply nested
1207      */
1208     public void testDeeplyNestedReadLocks() {
1209         final StampedLock lock = new StampedLock();
1210         final int depth = 300;
1211         final long[] stamps = new long[depth];
1212         final List<Function<StampedLock, Long>> readLockers = readLockers();
1213         final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers();
1214         for (int i = 0; i < depth; i++) {
1215             Function<StampedLock, Long> readLocker
1216                 = readLockers.get(i % readLockers.size());
1217             long stamp = readLocker.apply(lock);
1218             assertEquals(i + 1, lock.getReadLockCount());
1219             assertTrue(lock.isReadLocked());
1220             stamps[i] = stamp;
1221         }
1222         for (int i = 0; i < depth; i++) {
1223             BiConsumer<StampedLock, Long> readUnlocker
1224                 = readUnlockers.get(i % readUnlockers.size());
1225             assertEquals(depth - i, lock.getReadLockCount());
1226             assertTrue(lock.isReadLocked());
1227             readUnlocker.accept(lock, stamps[depth - 1 - i]);
1228         }
1229         assertUnlocked(lock);
1230     }
1231 
1232     /**
1233      * Stamped locks are not reentrant.
1234      */
1235     public void testNonReentrant() throws InterruptedException {
1236         final StampedLock lock = new StampedLock();
1237         long stamp;
1238 
1239         stamp = lock.writeLock();
1240         assertValid(lock, stamp);
1241         assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1242         assertEquals(0L, lock.tryReadLock(0L, DAYS));
1243         assertValid(lock, stamp);
1244         lock.unlockWrite(stamp);
1245 
1246         stamp = lock.tryWriteLock(1L, DAYS);
1247         assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1248         assertValid(lock, stamp);
1249         lock.unlockWrite(stamp);
1250 
1251         stamp = lock.readLock();
1252         assertEquals(0L, lock.tryWriteLock(0L, DAYS));
1253         assertValid(lock, stamp);
1254         lock.unlockRead(stamp);
1255     }
1256 
1257     /**
1258      * """StampedLocks have no notion of ownership. Locks acquired in
1259      * one thread can be released or converted in another."""
1260      */
1261     public void testNoOwnership() throws Throwable {
1262         ArrayList<Future<?>> futures = new ArrayList<>();
1263         for (Function<StampedLock, Long> writeLocker : writeLockers())
1264         for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) {
1265             StampedLock lock = new StampedLock();
1266             long stamp = writeLocker.apply(lock);
1267             futures.add(cachedThreadPool.submit(new CheckedRunnable() {
1268                 public void realRun() {
1269                     writeUnlocker.accept(lock, stamp);
1270                     assertUnlocked(lock);
1271                     assertFalse(lock.validate(stamp));
1272                 }}));
1273         }
1274         for (Future<?> future : futures)
1275             assertNull(future.get());
1276     }
1277 
1278     /** Tries out sample usage code from StampedLock javadoc. */
1279     public void testSampleUsage() throws Throwable {
1280         class Point {
1281             private double x, y;
1282             private final StampedLock sl = new StampedLock();
1283 
1284             void move(double deltaX, double deltaY) { // an exclusively locked method
1285                 long stamp = sl.writeLock();
1286                 try {
1287                     x += deltaX;
1288                     y += deltaY;
1289                 } finally {
1290                     sl.unlockWrite(stamp);
1291                 }
1292             }
1293 
1294             double distanceFromOrigin() { // A read-only method
1295                 double currentX, currentY;
1296                 long stamp = sl.tryOptimisticRead();
1297                 do {
1298                     if (stamp == 0L)
1299                         stamp = sl.readLock();
1300                     try {
1301                         // possibly racy reads
1302                         currentX = x;
1303                         currentY = y;
1304                     } finally {
1305                         stamp = sl.tryConvertToOptimisticRead(stamp);
1306                     }
1307                 } while (stamp == 0);
1308                 return Math.hypot(currentX, currentY);
1309             }
1310 
1311             double distanceFromOrigin2() {
1312                 long stamp = sl.tryOptimisticRead();
1313                 try {
1314                     retryHoldingLock:
1315                     for (;; stamp = sl.readLock()) {
1316                         if (stamp == 0L)
1317                             continue retryHoldingLock;
1318                         // possibly racy reads
1319                         double currentX = x;
1320                         double currentY = y;
1321                         if (!sl.validate(stamp))
1322                             continue retryHoldingLock;
1323                         return Math.hypot(currentX, currentY);
1324                     }
1325                 } finally {
1326                     if (StampedLock.isReadLockStamp(stamp))
1327                         sl.unlockRead(stamp);
1328                 }
1329             }
1330 
1331             void moveIfAtOrigin(double newX, double newY) {
1332                 long stamp = sl.readLock();
1333                 try {
1334                     while (x == 0.0 && y == 0.0) {
1335                         long ws = sl.tryConvertToWriteLock(stamp);
1336                         if (ws != 0L) {
1337                             stamp = ws;
1338                             x = newX;
1339                             y = newY;
1340                             return;
1341                         }
1342                         else {
1343                             sl.unlockRead(stamp);
1344                             stamp = sl.writeLock();
1345                         }
1346                     }
1347                 } finally {
1348                     sl.unlock(stamp);
1349                 }
1350             }
1351         }
1352 
1353         Point p = new Point();
1354         p.move(3.0, 4.0);
1355         assertEquals(5.0, p.distanceFromOrigin());
1356         p.moveIfAtOrigin(5.0, 12.0);
1357         assertEquals(5.0, p.distanceFromOrigin2());
1358     }
1359 
1360     /**
1361      * Stamp inspection methods work as expected, and do not inspect
1362      * the state of the lock itself.
1363      */
1364     public void testStampStateInspectionMethods() {
1365         StampedLock lock = new StampedLock();
1366 
1367         assertFalse(isWriteLockStamp(0L));
1368         assertFalse(isReadLockStamp(0L));
1369         assertFalse(isLockStamp(0L));
1370         assertFalse(isOptimisticReadStamp(0L));
1371 
1372         {
1373             long stamp = lock.writeLock();
1374             for (int i = 0; i < 2; i++) {
1375                 assertTrue(isWriteLockStamp(stamp));
1376                 assertFalse(isReadLockStamp(stamp));
1377                 assertTrue(isLockStamp(stamp));
1378                 assertFalse(isOptimisticReadStamp(stamp));
1379                 if (i == 0)
1380                     lock.unlockWrite(stamp);
1381             }
1382         }
1383 
1384         {
1385             long stamp = lock.readLock();
1386             for (int i = 0; i < 2; i++) {
1387                 assertFalse(isWriteLockStamp(stamp));
1388                 assertTrue(isReadLockStamp(stamp));
1389                 assertTrue(isLockStamp(stamp));
1390                 assertFalse(isOptimisticReadStamp(stamp));
1391                 if (i == 0)
1392                     lock.unlockRead(stamp);
1393             }
1394         }
1395 
1396         {
1397             long optimisticStamp = lock.tryOptimisticRead();
1398             long readStamp = lock.tryConvertToReadLock(optimisticStamp);
1399             long writeStamp = lock.tryConvertToWriteLock(readStamp);
1400             for (int i = 0; i < 2; i++) {
1401                 assertFalse(isWriteLockStamp(optimisticStamp));
1402                 assertFalse(isReadLockStamp(optimisticStamp));
1403                 assertFalse(isLockStamp(optimisticStamp));
1404                 assertTrue(isOptimisticReadStamp(optimisticStamp));
1405 
1406                 assertFalse(isWriteLockStamp(readStamp));
1407                 assertTrue(isReadLockStamp(readStamp));
1408                 assertTrue(isLockStamp(readStamp));
1409                 assertFalse(isOptimisticReadStamp(readStamp));
1410 
1411                 assertTrue(isWriteLockStamp(writeStamp));
1412                 assertFalse(isReadLockStamp(writeStamp));
1413                 assertTrue(isLockStamp(writeStamp));
1414                 assertFalse(isOptimisticReadStamp(writeStamp));
1415                 if (i == 0)
1416                     lock.unlockWrite(writeStamp);
1417             }
1418         }
1419     }
1420 
1421     /**
1422      * Multiple threads repeatedly contend for the same lock.
1423      */
1424     public void testConcurrentAccess() throws Exception {
1425         final StampedLock sl = new StampedLock();
1426         final Lock wl = sl.asWriteLock();
1427         final Lock rl = sl.asReadLock();
1428         final long testDurationMillis = expensiveTests ? 1000 : 2;
1429         final int nTasks = ThreadLocalRandom.current().nextInt(1, 10);
1430         final AtomicBoolean done = new AtomicBoolean(false);
1431         final List<CompletableFuture> futures = new ArrayList<>();
1432         final List<Callable<Long>> stampedWriteLockers = List.of(
1433             () -> sl.writeLock(),
1434             () -> writeLockInterruptiblyUninterrupted(sl),
1435             () -> tryWriteLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1436             () -> {
1437                 long stamp;
1438                 do { stamp = sl.tryConvertToWriteLock(sl.tryOptimisticRead()); }
1439                 while (stamp == 0L);
1440                 return stamp;
1441             },
1442             () -> {
1443               long stamp;
1444               do { stamp = sl.tryWriteLock(); } while (stamp == 0L);
1445               return stamp;
1446             },
1447             () -> {
1448               long stamp;
1449               do { stamp = sl.tryWriteLock(0L, DAYS); } while (stamp == 0L);
1450               return stamp;
1451             });
1452         final List<Callable<Long>> stampedReadLockers = List.of(
1453             () -> sl.readLock(),
1454             () -> readLockInterruptiblyUninterrupted(sl),
1455             () -> tryReadLockUninterrupted(sl, LONG_DELAY_MS, MILLISECONDS),
1456             () -> {
1457                 long stamp;
1458                 do { stamp = sl.tryConvertToReadLock(sl.tryOptimisticRead()); }
1459                 while (stamp == 0L);
1460                 return stamp;
1461             },
1462             () -> {
1463               long stamp;
1464               do { stamp = sl.tryReadLock(); } while (stamp == 0L);
1465               return stamp;
1466             },
1467             () -> {
1468               long stamp;
1469               do { stamp = sl.tryReadLock(0L, DAYS); } while (stamp == 0L);
1470               return stamp;
1471             });
1472         final List<Consumer<Long>> stampedWriteUnlockers = List.of(
1473             stamp -> sl.unlockWrite(stamp),
1474             stamp -> sl.unlock(stamp),
1475             stamp -> assertTrue(sl.tryUnlockWrite()),
1476             stamp -> wl.unlock(),
1477             stamp -> sl.tryConvertToOptimisticRead(stamp));
1478         final List<Consumer<Long>> stampedReadUnlockers = List.of(
1479             stamp -> sl.unlockRead(stamp),
1480             stamp -> sl.unlock(stamp),
1481             stamp -> assertTrue(sl.tryUnlockRead()),
1482             stamp -> rl.unlock(),
1483             stamp -> sl.tryConvertToOptimisticRead(stamp));
1484         final Action writer = () -> {
1485             // repeatedly acquires write lock
1486             var locker = chooseRandomly(stampedWriteLockers);
1487             var unlocker = chooseRandomly(stampedWriteUnlockers);
1488             while (!done.getAcquire()) {
1489                 long stamp = locker.call();
1490                 try {
1491                     assertTrue(isWriteLockStamp(stamp));
1492                     assertTrue(sl.isWriteLocked());
1493                     assertFalse(isReadLockStamp(stamp));
1494                     assertFalse(sl.isReadLocked());
1495                     assertEquals(0, sl.getReadLockCount());
1496                     assertTrue(sl.validate(stamp));
1497                 } finally {
1498                     unlocker.accept(stamp);
1499                 }
1500             }
1501         };
1502         final Action reader = () -> {
1503             // repeatedly acquires read lock
1504             var locker = chooseRandomly(stampedReadLockers);
1505             var unlocker = chooseRandomly(stampedReadUnlockers);
1506             while (!done.getAcquire()) {
1507                 long stamp = locker.call();
1508                 try {
1509                     assertFalse(isWriteLockStamp(stamp));
1510                     assertFalse(sl.isWriteLocked());
1511                     assertTrue(isReadLockStamp(stamp));
1512                     assertTrue(sl.isReadLocked());
1513                     assertTrue(sl.getReadLockCount() > 0);
1514                     assertTrue(sl.validate(stamp));
1515                 } finally {
1516                     unlocker.accept(stamp);
1517                 }
1518             }
1519         };
1520         for (int i = nTasks; i--> 0; ) {
1521             Action task = chooseRandomly(writer, reader);
1522             futures.add(CompletableFuture.runAsync(checkedRunnable(task)));
1523         }
1524         Thread.sleep(testDurationMillis);
1525         done.setRelease(true);
1526         for (var future : futures)
1527             checkTimedGet(future, null);
1528     }
1529 
1530 }