ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/StampedLockTest.java
Revision: 1.38
Committed: Thu Sep 21 17:52:52 2017 UTC (6 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.37: +46 -0 lines
Log Message:
add new tests testNonReentrant, testNoOwnership

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