ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.27
Committed: Wed Aug 10 17:05:13 2016 UTC (7 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.26: +583 -581 lines
Log Message:
more test scenarios

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