ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.36
Committed: Mon May 29 19:15:03 2017 UTC (6 years, 11 months ago) by jsr166
Branch: MAIN
Changes since 1.35: +4 -2 lines
Log Message:
more timeout handling rework; remove most uses of SMALL_DELAY_MS; randomize timeouts and TimeUnits; remove hardcoded 5 second timeouts

File Contents

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