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 package test.java.util.concurrent.tck; 36 import static java.util.concurrent.TimeUnit.DAYS; 37 import static java.util.concurrent.TimeUnit.MILLISECONDS; 38 import static java.util.concurrent.TimeUnit.SECONDS; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.concurrent.CountDownLatch; 43 import java.util.concurrent.Future; 44 import java.util.concurrent.TimeUnit; 45 import java.util.concurrent.locks.Lock; 46 import java.util.concurrent.locks.StampedLock; 47 import java.util.function.BiConsumer; 48 import java.util.function.Function; 49 50 import junit.framework.Test; 51 import junit.framework.TestSuite; 52 53 public class StampedLockTest extends JSR166TestCase { main(String[] args)54 public static void main(String[] args) { 55 main(suite(), args); 56 } suite()57 public static Test suite() { 58 return new TestSuite(StampedLockTest.class); 59 } 60 61 /** 62 * Releases write lock, checking isWriteLocked before and after 63 */ releaseWriteLock(StampedLock lock, long stamp)64 void releaseWriteLock(StampedLock lock, long stamp) { 65 assertTrue(lock.isWriteLocked()); 66 assertValid(lock, stamp); 67 lock.unlockWrite(stamp); 68 assertFalse(lock.isWriteLocked()); 69 assertFalse(lock.validate(stamp)); 70 } 71 72 /** 73 * Releases read lock, checking isReadLocked before and after 74 */ releaseReadLock(StampedLock lock, long stamp)75 void releaseReadLock(StampedLock lock, long stamp) { 76 assertTrue(lock.isReadLocked()); 77 assertValid(lock, stamp); 78 lock.unlockRead(stamp); 79 assertFalse(lock.isReadLocked()); 80 assertTrue(lock.validate(stamp)); 81 } 82 assertNonZero(long v)83 long assertNonZero(long v) { 84 assertTrue(v != 0L); 85 return v; 86 } 87 assertValid(StampedLock lock, long stamp)88 long assertValid(StampedLock lock, long stamp) { 89 assertTrue(stamp != 0L); 90 assertTrue(lock.validate(stamp)); 91 return stamp; 92 } 93 assertUnlocked(StampedLock lock)94 void assertUnlocked(StampedLock lock) { 95 assertFalse(lock.isReadLocked()); 96 assertFalse(lock.isWriteLocked()); 97 assertEquals(0, lock.getReadLockCount()); 98 assertValid(lock, lock.tryOptimisticRead()); 99 } 100 lockLockers(Lock lock)101 List<Action> lockLockers(Lock lock) { 102 List<Action> lockers = new ArrayList<>(); 103 lockers.add(() -> lock.lock()); 104 lockers.add(() -> lock.lockInterruptibly()); 105 lockers.add(() -> lock.tryLock()); 106 lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS)); 107 lockers.add(() -> lock.tryLock(0L, DAYS)); 108 lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS)); 109 return lockers; 110 } 111 readLockers()112 List<Function<StampedLock, Long>> readLockers() { 113 List<Function<StampedLock, Long>> readLockers = new ArrayList<>(); 114 readLockers.add(sl -> sl.readLock()); 115 readLockers.add(sl -> sl.tryReadLock()); 116 readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl)); 117 readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); 118 readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS)); 119 readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead())); 120 return readLockers; 121 } 122 readUnlockers()123 List<BiConsumer<StampedLock, Long>> readUnlockers() { 124 List<BiConsumer<StampedLock, Long>> readUnlockers = new ArrayList<>(); 125 readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp)); 126 readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead())); 127 readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock()); 128 readUnlockers.add((sl, stamp) -> sl.unlock(stamp)); 129 readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp))); 130 return readUnlockers; 131 } 132 writeLockers()133 List<Function<StampedLock, Long>> writeLockers() { 134 List<Function<StampedLock, Long>> writeLockers = new ArrayList<>(); 135 writeLockers.add(sl -> sl.writeLock()); 136 writeLockers.add(sl -> sl.tryWriteLock()); 137 writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl)); 138 writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); 139 writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS)); 140 writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead())); 141 return writeLockers; 142 } 143 writeUnlockers()144 List<BiConsumer<StampedLock, Long>> writeUnlockers() { 145 List<BiConsumer<StampedLock, Long>> writeUnlockers = new ArrayList<>(); 146 writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp)); 147 writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite())); 148 writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock()); 149 writeUnlockers.add((sl, stamp) -> sl.unlock(stamp)); 150 writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp))); 151 return writeUnlockers; 152 } 153 154 /** 155 * Constructed StampedLock is in unlocked state 156 */ testConstructor()157 public void testConstructor() { 158 assertUnlocked(new StampedLock()); 159 } 160 161 /** 162 * write-locking, then unlocking, an unlocked lock succeed 163 */ testWriteLock_lockUnlock()164 public void testWriteLock_lockUnlock() { 165 StampedLock lock = new StampedLock(); 166 167 for (Function<StampedLock, Long> writeLocker : writeLockers()) 168 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { 169 assertFalse(lock.isWriteLocked()); 170 assertFalse(lock.isReadLocked()); 171 assertEquals(0, lock.getReadLockCount()); 172 173 long s = writeLocker.apply(lock); 174 assertValid(lock, s); 175 assertTrue(lock.isWriteLocked()); 176 assertFalse(lock.isReadLocked()); 177 assertEquals(0, lock.getReadLockCount()); 178 writeUnlocker.accept(lock, s); 179 assertUnlocked(lock); 180 } 181 } 182 183 /** 184 * read-locking, then unlocking, an unlocked lock succeed 185 */ testReadLock_lockUnlock()186 public void testReadLock_lockUnlock() { 187 StampedLock lock = new StampedLock(); 188 189 for (Function<StampedLock, Long> readLocker : readLockers()) 190 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) { 191 long s = 42; 192 for (int i = 0; i < 2; i++) { 193 s = assertValid(lock, readLocker.apply(lock)); 194 assertFalse(lock.isWriteLocked()); 195 assertTrue(lock.isReadLocked()); 196 assertEquals(i + 1, lock.getReadLockCount()); 197 } 198 for (int i = 0; i < 2; i++) { 199 assertFalse(lock.isWriteLocked()); 200 assertTrue(lock.isReadLocked()); 201 assertEquals(2 - i, lock.getReadLockCount()); 202 readUnlocker.accept(lock, s); 203 } 204 assertUnlocked(lock); 205 } 206 } 207 208 /** 209 * tryUnlockWrite fails if not write locked 210 */ testTryUnlockWrite_failure()211 public void testTryUnlockWrite_failure() { 212 StampedLock lock = new StampedLock(); 213 assertFalse(lock.tryUnlockWrite()); 214 215 for (Function<StampedLock, Long> readLocker : readLockers()) 216 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) { 217 long s = assertValid(lock, readLocker.apply(lock)); 218 assertFalse(lock.tryUnlockWrite()); 219 assertTrue(lock.isReadLocked()); 220 readUnlocker.accept(lock, s); 221 assertUnlocked(lock); 222 } 223 } 224 225 /** 226 * tryUnlockRead fails if not read locked 227 */ testTryUnlockRead_failure()228 public void testTryUnlockRead_failure() { 229 StampedLock lock = new StampedLock(); 230 assertFalse(lock.tryUnlockRead()); 231 232 for (Function<StampedLock, Long> writeLocker : writeLockers()) 233 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { 234 long s = writeLocker.apply(lock); 235 assertFalse(lock.tryUnlockRead()); 236 assertTrue(lock.isWriteLocked()); 237 writeUnlocker.accept(lock, s); 238 assertUnlocked(lock); 239 } 240 } 241 242 /** 243 * validate(0L) fails 244 */ testValidate0()245 public void testValidate0() { 246 StampedLock lock = new StampedLock(); 247 assertFalse(lock.validate(0L)); 248 } 249 250 /** 251 * A stamp obtained from a successful lock operation validates while the lock is held 252 */ testValidate()253 public void testValidate() throws InterruptedException { 254 StampedLock lock = new StampedLock(); 255 256 for (Function<StampedLock, Long> readLocker : readLockers()) 257 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) { 258 long s = assertNonZero(readLocker.apply(lock)); 259 assertTrue(lock.validate(s)); 260 readUnlocker.accept(lock, s); 261 } 262 263 for (Function<StampedLock, Long> writeLocker : writeLockers()) 264 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { 265 long s = assertNonZero(writeLocker.apply(lock)); 266 assertTrue(lock.validate(s)); 267 writeUnlocker.accept(lock, s); 268 } 269 } 270 271 /** 272 * A stamp obtained from an unsuccessful lock operation does not validate 273 */ testValidate2()274 public void testValidate2() throws InterruptedException { 275 StampedLock lock = new StampedLock(); 276 long s = assertNonZero(lock.writeLock()); 277 assertTrue(lock.validate(s)); 278 assertFalse(lock.validate(lock.tryWriteLock())); 279 assertFalse(lock.validate(lock.tryWriteLock(0L, SECONDS))); 280 assertFalse(lock.validate(lock.tryReadLock())); 281 assertFalse(lock.validate(lock.tryReadLock(0L, SECONDS))); 282 assertFalse(lock.validate(lock.tryOptimisticRead())); 283 lock.unlockWrite(s); 284 } 285 assertThrowInterruptedExceptionWhenPreInterrupted(Action[] actions)286 void assertThrowInterruptedExceptionWhenPreInterrupted(Action[] actions) { 287 for (Action action : actions) { 288 Thread.currentThread().interrupt(); 289 try { 290 action.run(); 291 shouldThrow(); 292 } 293 catch (InterruptedException success) {} 294 catch (Throwable fail) { threadUnexpectedException(fail); } 295 assertFalse(Thread.interrupted()); 296 } 297 } 298 299 /** 300 * interruptible operations throw InterruptedException when pre-interrupted 301 */ testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted()302 public void testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted() { 303 final StampedLock lock = new StampedLock(); 304 305 Action[] interruptibleLockActions = { 306 () -> lock.writeLockInterruptibly(), 307 () -> lock.tryWriteLock(Long.MIN_VALUE, DAYS), 308 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS), 309 () -> lock.readLockInterruptibly(), 310 () -> lock.tryReadLock(Long.MIN_VALUE, DAYS), 311 () -> lock.tryReadLock(Long.MAX_VALUE, DAYS), 312 () -> lock.asWriteLock().lockInterruptibly(), 313 () -> lock.asWriteLock().tryLock(0L, DAYS), 314 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS), 315 () -> lock.asReadLock().lockInterruptibly(), 316 () -> lock.asReadLock().tryLock(0L, DAYS), 317 () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS), 318 }; 319 shuffle(interruptibleLockActions); 320 321 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions); 322 { 323 long s = lock.writeLock(); 324 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions); 325 lock.unlockWrite(s); 326 } 327 { 328 long s = lock.readLock(); 329 assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions); 330 lock.unlockRead(s); 331 } 332 } 333 assertThrowInterruptedExceptionWhenInterrupted(Action[] actions)334 void assertThrowInterruptedExceptionWhenInterrupted(Action[] actions) { 335 int n = actions.length; 336 Future<?>[] futures = new Future<?>[n]; 337 CountDownLatch threadsStarted = new CountDownLatch(n); 338 CountDownLatch done = new CountDownLatch(n); 339 340 for (int i = 0; i < n; i++) { 341 Action action = actions[i]; 342 futures[i] = cachedThreadPool.submit(new CheckedRunnable() { 343 public void realRun() throws Throwable { 344 threadsStarted.countDown(); 345 try { 346 action.run(); 347 shouldThrow(); 348 } 349 catch (InterruptedException success) {} 350 catch (Throwable fail) { threadUnexpectedException(fail); } 351 assertFalse(Thread.interrupted()); 352 done.countDown(); 353 }}); 354 } 355 356 await(threadsStarted); 357 assertEquals(n, done.getCount()); 358 for (Future<?> future : futures) // Interrupt all the tasks 359 future.cancel(true); 360 await(done); 361 } 362 363 /** 364 * interruptible operations throw InterruptedException when write locked and interrupted 365 */ testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted()366 public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() { 367 final StampedLock lock = new StampedLock(); 368 long s = lock.writeLock(); 369 370 Action[] interruptibleLockBlockingActions = { 371 () -> lock.writeLockInterruptibly(), 372 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS), 373 () -> lock.readLockInterruptibly(), 374 () -> lock.tryReadLock(Long.MAX_VALUE, DAYS), 375 () -> lock.asWriteLock().lockInterruptibly(), 376 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS), 377 () -> lock.asReadLock().lockInterruptibly(), 378 () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS), 379 }; 380 shuffle(interruptibleLockBlockingActions); 381 382 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions); 383 } 384 385 /** 386 * interruptible operations throw InterruptedException when read locked and interrupted 387 */ testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted()388 public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() { 389 final StampedLock lock = new StampedLock(); 390 long s = lock.readLock(); 391 392 Action[] interruptibleLockBlockingActions = { 393 () -> lock.writeLockInterruptibly(), 394 () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS), 395 () -> lock.asWriteLock().lockInterruptibly(), 396 () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS), 397 }; 398 shuffle(interruptibleLockBlockingActions); 399 400 assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions); 401 } 402 403 /** 404 * Non-interruptible operations ignore and preserve interrupt status 405 */ testNonInterruptibleOperationsIgnoreInterrupts()406 public void testNonInterruptibleOperationsIgnoreInterrupts() { 407 final StampedLock lock = new StampedLock(); 408 Thread.currentThread().interrupt(); 409 410 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) { 411 long s = assertValid(lock, lock.readLock()); 412 readUnlocker.accept(lock, s); 413 s = assertValid(lock, lock.tryReadLock()); 414 readUnlocker.accept(lock, s); 415 } 416 417 lock.asReadLock().lock(); 418 lock.asReadLock().unlock(); 419 420 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { 421 long s = assertValid(lock, lock.writeLock()); 422 writeUnlocker.accept(lock, s); 423 s = assertValid(lock, lock.tryWriteLock()); 424 writeUnlocker.accept(lock, s); 425 } 426 427 lock.asWriteLock().lock(); 428 lock.asWriteLock().unlock(); 429 430 assertTrue(Thread.interrupted()); 431 } 432 433 /** 434 * tryWriteLock on an unlocked lock succeeds 435 */ testTryWriteLock()436 public void testTryWriteLock() { 437 final StampedLock lock = new StampedLock(); 438 long s = lock.tryWriteLock(); 439 assertTrue(s != 0L); 440 assertTrue(lock.isWriteLocked()); 441 assertEquals(0L, lock.tryWriteLock()); 442 releaseWriteLock(lock, s); 443 } 444 445 /** 446 * tryWriteLock fails if locked 447 */ testTryWriteLockWhenLocked()448 public void testTryWriteLockWhenLocked() { 449 final StampedLock lock = new StampedLock(); 450 long s = lock.writeLock(); 451 Thread t = newStartedThread(new CheckedRunnable() { 452 public void realRun() { 453 assertEquals(0L, lock.tryWriteLock()); 454 }}); 455 456 assertEquals(0L, lock.tryWriteLock()); 457 awaitTermination(t); 458 releaseWriteLock(lock, s); 459 } 460 461 /** 462 * tryReadLock fails if write-locked 463 */ testTryReadLockWhenLocked()464 public void testTryReadLockWhenLocked() { 465 final StampedLock lock = new StampedLock(); 466 long s = lock.writeLock(); 467 Thread t = newStartedThread(new CheckedRunnable() { 468 public void realRun() { 469 assertEquals(0L, lock.tryReadLock()); 470 }}); 471 472 assertEquals(0L, lock.tryReadLock()); 473 awaitTermination(t); 474 releaseWriteLock(lock, s); 475 } 476 477 /** 478 * Multiple threads can hold a read lock when not write-locked 479 */ testMultipleReadLocks()480 public void testMultipleReadLocks() { 481 final StampedLock lock = new StampedLock(); 482 final long s = lock.readLock(); 483 Thread t = newStartedThread(new CheckedRunnable() { 484 public void realRun() throws InterruptedException { 485 long s2 = lock.tryReadLock(); 486 assertValid(lock, s2); 487 lock.unlockRead(s2); 488 long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS); 489 assertValid(lock, s3); 490 lock.unlockRead(s3); 491 long s4 = lock.readLock(); 492 assertValid(lock, s4); 493 lock.unlockRead(s4); 494 lock.asReadLock().lock(); 495 lock.asReadLock().unlock(); 496 lock.asReadLock().lockInterruptibly(); 497 lock.asReadLock().unlock(); 498 lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS); 499 lock.asReadLock().unlock(); 500 }}); 501 502 awaitTermination(t); 503 lock.unlockRead(s); 504 } 505 506 /** 507 * writeLock() succeeds only after a reading thread unlocks 508 */ testWriteAfterReadLock()509 public void testWriteAfterReadLock() throws InterruptedException { 510 final CountDownLatch aboutToLock = new CountDownLatch(1); 511 final StampedLock lock = new StampedLock(); 512 long rs = lock.readLock(); 513 Thread t = newStartedThread(new CheckedRunnable() { 514 public void realRun() { 515 aboutToLock.countDown(); 516 long s = lock.writeLock(); 517 assertTrue(lock.isWriteLocked()); 518 assertFalse(lock.isReadLocked()); 519 lock.unlockWrite(s); 520 }}); 521 522 aboutToLock.await(); 523 waitForThreadToEnterWaitState(t); 524 assertFalse(lock.isWriteLocked()); 525 assertTrue(lock.isReadLocked()); 526 lock.unlockRead(rs); 527 awaitTermination(t); 528 assertUnlocked(lock); 529 } 530 531 /** 532 * writeLock() succeeds only after reading threads unlock 533 */ testWriteAfterMultipleReadLocks()534 public void testWriteAfterMultipleReadLocks() { 535 final StampedLock lock = new StampedLock(); 536 long s = lock.readLock(); 537 Thread t1 = newStartedThread(new CheckedRunnable() { 538 public void realRun() { 539 long rs = lock.readLock(); 540 lock.unlockRead(rs); 541 }}); 542 543 awaitTermination(t1); 544 545 Thread t2 = newStartedThread(new CheckedRunnable() { 546 public void realRun() { 547 long ws = lock.writeLock(); 548 lock.unlockWrite(ws); 549 }}); 550 551 assertTrue(lock.isReadLocked()); 552 assertFalse(lock.isWriteLocked()); 553 lock.unlockRead(s); 554 awaitTermination(t2); 555 assertUnlocked(lock); 556 } 557 558 /** 559 * readLock() succeed only after a writing thread unlocks 560 */ testReadAfterWriteLock()561 public void testReadAfterWriteLock() { 562 final StampedLock lock = new StampedLock(); 563 final CountDownLatch threadsStarted = new CountDownLatch(2); 564 final long s = lock.writeLock(); 565 final Runnable acquireReleaseReadLock = new CheckedRunnable() { 566 public void realRun() { 567 threadsStarted.countDown(); 568 long rs = lock.readLock(); 569 assertTrue(lock.isReadLocked()); 570 assertFalse(lock.isWriteLocked()); 571 lock.unlockRead(rs); 572 }}; 573 Thread t1 = newStartedThread(acquireReleaseReadLock); 574 Thread t2 = newStartedThread(acquireReleaseReadLock); 575 576 await(threadsStarted); 577 waitForThreadToEnterWaitState(t1); 578 waitForThreadToEnterWaitState(t2); 579 assertTrue(lock.isWriteLocked()); 580 assertFalse(lock.isReadLocked()); 581 releaseWriteLock(lock, s); 582 awaitTermination(t1); 583 awaitTermination(t2); 584 assertUnlocked(lock); 585 } 586 587 /** 588 * tryReadLock succeeds if read locked but not write locked 589 */ testTryLockWhenReadLocked()590 public void testTryLockWhenReadLocked() { 591 final StampedLock lock = new StampedLock(); 592 long s = lock.readLock(); 593 Thread t = newStartedThread(new CheckedRunnable() { 594 public void realRun() { 595 long rs = lock.tryReadLock(); 596 assertValid(lock, rs); 597 lock.unlockRead(rs); 598 }}); 599 600 awaitTermination(t); 601 lock.unlockRead(s); 602 } 603 604 /** 605 * tryWriteLock fails when read locked 606 */ testTryWriteLockWhenReadLocked()607 public void testTryWriteLockWhenReadLocked() { 608 final StampedLock lock = new StampedLock(); 609 long s = lock.readLock(); 610 Thread t = newStartedThread(new CheckedRunnable() { 611 public void realRun() { 612 threadAssertEquals(0L, lock.tryWriteLock()); 613 }}); 614 615 awaitTermination(t); 616 lock.unlockRead(s); 617 } 618 619 /** 620 * timed lock operations time out if lock not available 621 */ testTimedLock_Timeout()622 public void testTimedLock_Timeout() throws Exception { 623 ArrayList<Future<?>> futures = new ArrayList<>(); 624 625 // Write locked 626 final StampedLock lock = new StampedLock(); 627 long stamp = lock.writeLock(); 628 assertEquals(0L, lock.tryReadLock(0L, DAYS)); 629 assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS)); 630 assertFalse(lock.asReadLock().tryLock(0L, DAYS)); 631 assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS)); 632 assertEquals(0L, lock.tryWriteLock(0L, DAYS)); 633 assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS)); 634 assertFalse(lock.asWriteLock().tryLock(0L, DAYS)); 635 assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS)); 636 637 futures.add(cachedThreadPool.submit(new CheckedRunnable() { 638 public void realRun() throws InterruptedException { 639 long startTime = System.nanoTime(); 640 assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS)); 641 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 642 }})); 643 644 futures.add(cachedThreadPool.submit(new CheckedRunnable() { 645 public void realRun() throws InterruptedException { 646 long startTime = System.nanoTime(); 647 assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS)); 648 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 649 }})); 650 651 // Read locked 652 final StampedLock lock2 = new StampedLock(); 653 long stamp2 = lock2.readLock(); 654 assertEquals(0L, lock2.tryWriteLock(0L, DAYS)); 655 assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS)); 656 assertFalse(lock2.asWriteLock().tryLock(0L, DAYS)); 657 assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS)); 658 659 futures.add(cachedThreadPool.submit(new CheckedRunnable() { 660 public void realRun() throws InterruptedException { 661 long startTime = System.nanoTime(); 662 assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS)); 663 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 664 }})); 665 666 for (Future<?> future : futures) 667 assertNull(future.get()); 668 669 releaseWriteLock(lock, stamp); 670 releaseReadLock(lock2, stamp2); 671 } 672 673 /** 674 * writeLockInterruptibly succeeds if unlocked 675 */ testWriteLockInterruptibly()676 public void testWriteLockInterruptibly() throws InterruptedException { 677 final StampedLock lock = new StampedLock(); 678 long s = lock.writeLockInterruptibly(); 679 assertTrue(lock.isWriteLocked()); 680 releaseWriteLock(lock, s); 681 } 682 683 /** 684 * readLockInterruptibly succeeds if lock free 685 */ testReadLockInterruptibly()686 public void testReadLockInterruptibly() throws InterruptedException { 687 final StampedLock lock = new StampedLock(); 688 689 long s = assertValid(lock, lock.readLockInterruptibly()); 690 assertTrue(lock.isReadLocked()); 691 lock.unlockRead(s); 692 693 lock.asReadLock().lockInterruptibly(); 694 assertTrue(lock.isReadLocked()); 695 lock.asReadLock().unlock(); 696 } 697 698 /** 699 * A serialized lock deserializes as unlocked 700 */ testSerialization()701 public void testSerialization() { 702 StampedLock lock = new StampedLock(); 703 lock.writeLock(); 704 StampedLock clone = serialClone(lock); 705 assertTrue(lock.isWriteLocked()); 706 assertFalse(clone.isWriteLocked()); 707 long s = clone.writeLock(); 708 assertTrue(clone.isWriteLocked()); 709 clone.unlockWrite(s); 710 assertFalse(clone.isWriteLocked()); 711 } 712 713 /** 714 * toString indicates current lock state 715 */ testToString()716 public void testToString() { 717 StampedLock lock = new StampedLock(); 718 assertTrue(lock.toString().contains("Unlocked")); 719 long s = lock.writeLock(); 720 assertTrue(lock.toString().contains("Write-locked")); 721 lock.unlockWrite(s); 722 s = lock.readLock(); 723 assertTrue(lock.toString().contains("Read-locks")); 724 } 725 726 /** 727 * tryOptimisticRead succeeds and validates if unlocked, fails if 728 * exclusively locked 729 */ testValidateOptimistic()730 public void testValidateOptimistic() throws InterruptedException { 731 StampedLock lock = new StampedLock(); 732 733 assertValid(lock, lock.tryOptimisticRead()); 734 735 for (Function<StampedLock, Long> writeLocker : writeLockers()) { 736 long s = assertValid(lock, writeLocker.apply(lock)); 737 assertEquals(0L, lock.tryOptimisticRead()); 738 releaseWriteLock(lock, s); 739 } 740 741 for (Function<StampedLock, Long> readLocker : readLockers()) { 742 long s = assertValid(lock, readLocker.apply(lock)); 743 long p = assertValid(lock, lock.tryOptimisticRead()); 744 releaseReadLock(lock, s); 745 assertTrue(lock.validate(p)); 746 } 747 748 assertValid(lock, lock.tryOptimisticRead()); 749 } 750 751 /** 752 * tryOptimisticRead stamp does not validate if a write lock intervenes 753 */ testValidateOptimisticWriteLocked()754 public void testValidateOptimisticWriteLocked() { 755 final StampedLock lock = new StampedLock(); 756 final long p = assertValid(lock, lock.tryOptimisticRead()); 757 final long s = assertValid(lock, lock.writeLock()); 758 assertFalse(lock.validate(p)); 759 assertEquals(0L, lock.tryOptimisticRead()); 760 assertTrue(lock.validate(s)); 761 lock.unlockWrite(s); 762 } 763 764 /** 765 * tryOptimisticRead stamp does not validate if a write lock 766 * intervenes in another thread 767 */ testValidateOptimisticWriteLocked2()768 public void testValidateOptimisticWriteLocked2() 769 throws InterruptedException { 770 final CountDownLatch locked = new CountDownLatch(1); 771 final StampedLock lock = new StampedLock(); 772 final long p = assertValid(lock, lock.tryOptimisticRead()); 773 774 Thread t = newStartedThread(new CheckedInterruptedRunnable() { 775 public void realRun() throws InterruptedException { 776 lock.writeLockInterruptibly(); 777 locked.countDown(); 778 lock.writeLockInterruptibly(); 779 }}); 780 781 locked.await(); 782 assertFalse(lock.validate(p)); 783 assertEquals(0L, lock.tryOptimisticRead()); 784 waitForThreadToEnterWaitState(t); 785 t.interrupt(); 786 awaitTermination(t); 787 assertTrue(lock.isWriteLocked()); 788 } 789 790 /** 791 * tryConvertToOptimisticRead succeeds and validates if successfully locked 792 */ testTryConvertToOptimisticRead()793 public void testTryConvertToOptimisticRead() throws InterruptedException { 794 StampedLock lock = new StampedLock(); 795 long s, p, q; 796 assertEquals(0L, lock.tryConvertToOptimisticRead(0L)); 797 798 s = assertValid(lock, lock.tryOptimisticRead()); 799 assertEquals(s, lock.tryConvertToOptimisticRead(s)); 800 assertTrue(lock.validate(s)); 801 802 for (Function<StampedLock, Long> writeLocker : writeLockers()) { 803 s = assertValid(lock, writeLocker.apply(lock)); 804 p = assertValid(lock, lock.tryConvertToOptimisticRead(s)); 805 assertFalse(lock.validate(s)); 806 assertTrue(lock.validate(p)); 807 assertUnlocked(lock); 808 } 809 810 for (Function<StampedLock, Long> readLocker : readLockers()) { 811 s = assertValid(lock, readLocker.apply(lock)); 812 q = assertValid(lock, lock.tryOptimisticRead()); 813 assertEquals(q, lock.tryConvertToOptimisticRead(q)); 814 assertTrue(lock.validate(q)); 815 assertTrue(lock.isReadLocked()); 816 p = assertValid(lock, lock.tryConvertToOptimisticRead(s)); 817 assertTrue(lock.validate(p)); 818 assertTrue(lock.validate(s)); 819 assertUnlocked(lock); 820 assertEquals(q, lock.tryConvertToOptimisticRead(q)); 821 assertTrue(lock.validate(q)); 822 } 823 } 824 825 /** 826 * tryConvertToReadLock succeeds for valid stamps 827 */ testTryConvertToReadLock()828 public void testTryConvertToReadLock() throws InterruptedException { 829 StampedLock lock = new StampedLock(); 830 long s, p; 831 832 assertEquals(0L, lock.tryConvertToReadLock(0L)); 833 834 s = assertValid(lock, lock.tryOptimisticRead()); 835 p = assertValid(lock, lock.tryConvertToReadLock(s)); 836 assertTrue(lock.isReadLocked()); 837 assertEquals(1, lock.getReadLockCount()); 838 assertTrue(lock.validate(s)); 839 lock.unlockRead(p); 840 841 s = assertValid(lock, lock.tryOptimisticRead()); 842 lock.readLock(); 843 p = assertValid(lock, lock.tryConvertToReadLock(s)); 844 assertTrue(lock.isReadLocked()); 845 assertEquals(2, lock.getReadLockCount()); 846 lock.unlockRead(p); 847 lock.unlockRead(p); 848 assertUnlocked(lock); 849 850 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) { 851 for (Function<StampedLock, Long> writeLocker : writeLockers()) { 852 s = assertValid(lock, writeLocker.apply(lock)); 853 p = assertValid(lock, lock.tryConvertToReadLock(s)); 854 assertFalse(lock.validate(s)); 855 assertTrue(lock.isReadLocked()); 856 assertEquals(1, lock.getReadLockCount()); 857 readUnlocker.accept(lock, p); 858 } 859 860 for (Function<StampedLock, Long> readLocker : readLockers()) { 861 s = assertValid(lock, readLocker.apply(lock)); 862 assertEquals(s, lock.tryConvertToReadLock(s)); 863 assertTrue(lock.validate(s)); 864 assertTrue(lock.isReadLocked()); 865 assertEquals(1, lock.getReadLockCount()); 866 readUnlocker.accept(lock, s); 867 } 868 } 869 } 870 871 /** 872 * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked 873 */ testTryConvertToWriteLock()874 public void testTryConvertToWriteLock() throws InterruptedException { 875 StampedLock lock = new StampedLock(); 876 long s, p; 877 878 assertEquals(0L, lock.tryConvertToWriteLock(0L)); 879 880 assertTrue((s = lock.tryOptimisticRead()) != 0L); 881 assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); 882 assertTrue(lock.isWriteLocked()); 883 lock.unlockWrite(p); 884 885 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { 886 for (Function<StampedLock, Long> writeLocker : writeLockers()) { 887 s = assertValid(lock, writeLocker.apply(lock)); 888 assertEquals(s, lock.tryConvertToWriteLock(s)); 889 assertTrue(lock.validate(s)); 890 assertTrue(lock.isWriteLocked()); 891 writeUnlocker.accept(lock, s); 892 } 893 894 for (Function<StampedLock, Long> readLocker : readLockers()) { 895 s = assertValid(lock, readLocker.apply(lock)); 896 p = assertValid(lock, lock.tryConvertToWriteLock(s)); 897 assertFalse(lock.validate(s)); 898 assertTrue(lock.validate(p)); 899 assertTrue(lock.isWriteLocked()); 900 writeUnlocker.accept(lock, p); 901 } 902 } 903 904 // failure if multiply read locked 905 for (Function<StampedLock, Long> readLocker : readLockers()) { 906 s = assertValid(lock, readLocker.apply(lock)); 907 p = assertValid(lock, readLocker.apply(lock)); 908 assertEquals(0L, lock.tryConvertToWriteLock(s)); 909 assertTrue(lock.validate(s)); 910 assertTrue(lock.validate(p)); 911 assertEquals(2, lock.getReadLockCount()); 912 lock.unlock(p); 913 lock.unlock(s); 914 assertUnlocked(lock); 915 } 916 } 917 918 /** 919 * asWriteLock can be locked and unlocked 920 */ testAsWriteLock()921 public void testAsWriteLock() throws Throwable { 922 StampedLock sl = new StampedLock(); 923 Lock lock = sl.asWriteLock(); 924 for (Action locker : lockLockers(lock)) { 925 locker.run(); 926 assertTrue(sl.isWriteLocked()); 927 assertFalse(sl.isReadLocked()); 928 assertFalse(lock.tryLock()); 929 lock.unlock(); 930 assertUnlocked(sl); 931 } 932 } 933 934 /** 935 * asReadLock can be locked and unlocked 936 */ testAsReadLock()937 public void testAsReadLock() throws Throwable { 938 StampedLock sl = new StampedLock(); 939 Lock lock = sl.asReadLock(); 940 for (Action locker : lockLockers(lock)) { 941 locker.run(); 942 assertTrue(sl.isReadLocked()); 943 assertFalse(sl.isWriteLocked()); 944 assertEquals(1, sl.getReadLockCount()); 945 locker.run(); 946 assertTrue(sl.isReadLocked()); 947 assertEquals(2, sl.getReadLockCount()); 948 lock.unlock(); 949 lock.unlock(); 950 assertUnlocked(sl); 951 } 952 } 953 954 /** 955 * asReadWriteLock.writeLock can be locked and unlocked 956 */ testAsReadWriteLockWriteLock()957 public void testAsReadWriteLockWriteLock() throws Throwable { 958 StampedLock sl = new StampedLock(); 959 Lock lock = sl.asReadWriteLock().writeLock(); 960 for (Action locker : lockLockers(lock)) { 961 locker.run(); 962 assertTrue(sl.isWriteLocked()); 963 assertFalse(sl.isReadLocked()); 964 assertFalse(lock.tryLock()); 965 lock.unlock(); 966 assertUnlocked(sl); 967 } 968 } 969 970 /** 971 * asReadWriteLock.readLock can be locked and unlocked 972 */ testAsReadWriteLockReadLock()973 public void testAsReadWriteLockReadLock() throws Throwable { 974 StampedLock sl = new StampedLock(); 975 Lock lock = sl.asReadWriteLock().readLock(); 976 for (Action locker : lockLockers(lock)) { 977 locker.run(); 978 assertTrue(sl.isReadLocked()); 979 assertFalse(sl.isWriteLocked()); 980 assertEquals(1, sl.getReadLockCount()); 981 locker.run(); 982 assertTrue(sl.isReadLocked()); 983 assertEquals(2, sl.getReadLockCount()); 984 lock.unlock(); 985 lock.unlock(); 986 assertUnlocked(sl); 987 } 988 } 989 990 /** 991 * Lock.newCondition throws UnsupportedOperationException 992 */ testLockViewsDoNotSupportConditions()993 public void testLockViewsDoNotSupportConditions() { 994 StampedLock sl = new StampedLock(); 995 assertThrows(UnsupportedOperationException.class, 996 () -> sl.asWriteLock().newCondition(), 997 () -> sl.asReadLock().newCondition(), 998 () -> sl.asReadWriteLock().writeLock().newCondition(), 999 () -> sl.asReadWriteLock().readLock().newCondition()); 1000 } 1001 1002 /** 1003 * Passing optimistic read stamps to unlock operations result in 1004 * IllegalMonitorStateException 1005 */ testCannotUnlockOptimisticReadStamps()1006 public void testCannotUnlockOptimisticReadStamps() { 1007 Runnable[] actions = { 1008 () -> { 1009 StampedLock sl = new StampedLock(); 1010 long stamp = assertValid(sl, sl.tryOptimisticRead()); 1011 sl.unlockRead(stamp); 1012 }, 1013 () -> { 1014 StampedLock sl = new StampedLock(); 1015 long stamp = sl.tryOptimisticRead(); 1016 sl.unlock(stamp); 1017 }, 1018 1019 () -> { 1020 StampedLock sl = new StampedLock(); 1021 long stamp = sl.tryOptimisticRead(); 1022 sl.writeLock(); 1023 sl.unlock(stamp); 1024 }, 1025 () -> { 1026 StampedLock sl = new StampedLock(); 1027 sl.readLock(); 1028 long stamp = assertValid(sl, sl.tryOptimisticRead()); 1029 sl.unlockRead(stamp); 1030 }, 1031 () -> { 1032 StampedLock sl = new StampedLock(); 1033 sl.readLock(); 1034 long stamp = assertValid(sl, sl.tryOptimisticRead()); 1035 sl.unlock(stamp); 1036 }, 1037 1038 () -> { 1039 StampedLock sl = new StampedLock(); 1040 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); 1041 assertValid(sl, stamp); 1042 sl.writeLock(); 1043 sl.unlockWrite(stamp); 1044 }, 1045 () -> { 1046 StampedLock sl = new StampedLock(); 1047 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); 1048 sl.writeLock(); 1049 sl.unlock(stamp); 1050 }, 1051 () -> { 1052 StampedLock sl = new StampedLock(); 1053 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); 1054 sl.readLock(); 1055 sl.unlockRead(stamp); 1056 }, 1057 () -> { 1058 StampedLock sl = new StampedLock(); 1059 long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); 1060 sl.readLock(); 1061 sl.unlock(stamp); 1062 }, 1063 1064 () -> { 1065 StampedLock sl = new StampedLock(); 1066 long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); 1067 assertValid(sl, stamp); 1068 sl.writeLock(); 1069 sl.unlockWrite(stamp); 1070 }, 1071 () -> { 1072 StampedLock sl = new StampedLock(); 1073 long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); 1074 sl.writeLock(); 1075 sl.unlock(stamp); 1076 }, 1077 () -> { 1078 StampedLock sl = new StampedLock(); 1079 long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); 1080 sl.readLock(); 1081 sl.unlockRead(stamp); 1082 }, 1083 () -> { 1084 StampedLock sl = new StampedLock(); 1085 sl.readLock(); 1086 long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); 1087 assertValid(sl, stamp); 1088 sl.readLock(); 1089 sl.unlockRead(stamp); 1090 }, 1091 () -> { 1092 StampedLock sl = new StampedLock(); 1093 long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); 1094 sl.readLock(); 1095 sl.unlock(stamp); 1096 }, 1097 () -> { 1098 StampedLock sl = new StampedLock(); 1099 sl.readLock(); 1100 long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); 1101 sl.readLock(); 1102 sl.unlock(stamp); 1103 }, 1104 }; 1105 1106 assertThrows(IllegalMonitorStateException.class, actions); 1107 } 1108 writeLockInterruptiblyUninterrupted(StampedLock sl)1109 static long writeLockInterruptiblyUninterrupted(StampedLock sl) { 1110 try { return sl.writeLockInterruptibly(); } 1111 catch (InterruptedException ex) { throw new AssertionError(ex); } 1112 } 1113 tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit)1114 static long tryWriteLockUninterrupted(StampedLock sl, long time, TimeUnit unit) { 1115 try { return sl.tryWriteLock(time, unit); } 1116 catch (InterruptedException ex) { throw new AssertionError(ex); } 1117 } 1118 readLockInterruptiblyUninterrupted(StampedLock sl)1119 static long readLockInterruptiblyUninterrupted(StampedLock sl) { 1120 try { return sl.readLockInterruptibly(); } 1121 catch (InterruptedException ex) { throw new AssertionError(ex); } 1122 } 1123 tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit)1124 static long tryReadLockUninterrupted(StampedLock sl, long time, TimeUnit unit) { 1125 try { return sl.tryReadLock(time, unit); } 1126 catch (InterruptedException ex) { throw new AssertionError(ex); } 1127 } 1128 1129 /** 1130 * Invalid stamps result in IllegalMonitorStateException 1131 */ testInvalidStampsThrowIllegalMonitorStateException()1132 public void testInvalidStampsThrowIllegalMonitorStateException() { 1133 final StampedLock sl = new StampedLock(); 1134 1135 assertThrows(IllegalMonitorStateException.class, 1136 () -> sl.unlockWrite(0L), 1137 () -> sl.unlockRead(0L), 1138 () -> sl.unlock(0L)); 1139 1140 final long optimisticStamp = sl.tryOptimisticRead(); 1141 final long readStamp = sl.readLock(); 1142 sl.unlockRead(readStamp); 1143 final long writeStamp = sl.writeLock(); 1144 sl.unlockWrite(writeStamp); 1145 assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L); 1146 final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp }; 1147 final Runnable assertNoLongerValidStampsThrow = () -> { 1148 for (long noLongerValidStamp : noLongerValidStamps) 1149 assertThrows(IllegalMonitorStateException.class, 1150 () -> sl.unlockWrite(noLongerValidStamp), 1151 () -> sl.unlockRead(noLongerValidStamp), 1152 () -> sl.unlock(noLongerValidStamp)); 1153 }; 1154 assertNoLongerValidStampsThrow.run(); 1155 1156 for (Function<StampedLock, Long> readLocker : readLockers()) 1157 for (BiConsumer<StampedLock, Long> readUnlocker : readUnlockers()) { 1158 final long stamp = readLocker.apply(sl); 1159 assertValid(sl, stamp); 1160 assertNoLongerValidStampsThrow.run(); 1161 assertThrows(IllegalMonitorStateException.class, 1162 () -> sl.unlockWrite(stamp), 1163 () -> sl.unlockRead(sl.tryOptimisticRead()), 1164 () -> sl.unlockRead(0L)); 1165 readUnlocker.accept(sl, stamp); 1166 assertUnlocked(sl); 1167 assertNoLongerValidStampsThrow.run(); 1168 } 1169 1170 for (Function<StampedLock, Long> writeLocker : writeLockers()) 1171 for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { 1172 final long stamp = writeLocker.apply(sl); 1173 assertValid(sl, stamp); 1174 assertNoLongerValidStampsThrow.run(); 1175 assertThrows(IllegalMonitorStateException.class, 1176 () -> sl.unlockRead(stamp), 1177 () -> sl.unlockWrite(0L)); 1178 writeUnlocker.accept(sl, stamp); 1179 assertUnlocked(sl); 1180 assertNoLongerValidStampsThrow.run(); 1181 } 1182 } 1183 1184 /** 1185 * Read locks can be very deeply nested 1186 */ testDeeplyNestedReadLocks()1187 public void testDeeplyNestedReadLocks() { 1188 final StampedLock lock = new StampedLock(); 1189 final int depth = 300; 1190 final long[] stamps = new long[depth]; 1191 final List<Function<StampedLock, Long>> readLockers = readLockers(); 1192 final List<BiConsumer<StampedLock, Long>> readUnlockers = readUnlockers(); 1193 for (int i = 0; i < depth; i++) { 1194 Function<StampedLock, Long> readLocker 1195 = readLockers.get(i % readLockers.size()); 1196 long stamp = readLocker.apply(lock); 1197 assertEquals(i + 1, lock.getReadLockCount()); 1198 assertTrue(lock.isReadLocked()); 1199 stamps[i] = stamp; 1200 } 1201 for (int i = 0; i < depth; i++) { 1202 BiConsumer<StampedLock, Long> readUnlocker 1203 = readUnlockers.get(i % readUnlockers.size()); 1204 assertEquals(depth - i, lock.getReadLockCount()); 1205 assertTrue(lock.isReadLocked()); 1206 readUnlocker.accept(lock, stamps[depth - 1 - i]); 1207 } 1208 assertUnlocked(lock); 1209 } 1210 } 1211