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; |
10 |
|
|
11 |
|
import java.util.ArrayList; |
12 |
|
import java.util.List; |
247 |
|
long s = assertNonZero(lock.writeLock()); |
248 |
|
assertTrue(lock.validate(s)); |
249 |
|
assertFalse(lock.validate(lock.tryWriteLock())); |
250 |
< |
assertFalse(lock.validate(lock.tryWriteLock(0L, SECONDS))); |
250 |
> |
assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(), |
251 |
> |
randomTimeUnit()))); |
252 |
|
assertFalse(lock.validate(lock.tryReadLock())); |
253 |
< |
assertFalse(lock.validate(lock.tryReadLock(0L, SECONDS))); |
253 |
> |
assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(), |
254 |
> |
randomTimeUnit()))); |
255 |
|
assertFalse(lock.validate(lock.tryOptimisticRead())); |
256 |
|
lock.unlockWrite(s); |
257 |
|
} |
493 |
|
}}); |
494 |
|
|
495 |
|
await(aboutToLock); |
496 |
< |
waitForThreadToEnterWaitState(t); |
496 |
> |
assertThreadBlocks(t, Thread.State.WAITING); |
497 |
|
assertFalse(lock.isWriteLocked()); |
498 |
|
assertTrue(lock.isReadLocked()); |
499 |
|
lock.unlockRead(rs); |
547 |
|
Thread t2 = newStartedThread(acquireReleaseReadLock); |
548 |
|
|
549 |
|
await(threadsStarted); |
550 |
< |
waitForThreadToEnterWaitState(t1); |
551 |
< |
waitForThreadToEnterWaitState(t2); |
550 |
> |
assertThreadBlocks(t1, Thread.State.WAITING); |
551 |
> |
assertThreadBlocks(t2, Thread.State.WAITING); |
552 |
|
assertTrue(lock.isWriteLocked()); |
553 |
|
assertFalse(lock.isReadLocked()); |
554 |
|
releaseWriteLock(lock, s); |
754 |
|
await(locked); |
755 |
|
assertFalse(lock.validate(p)); |
756 |
|
assertEquals(0L, lock.tryOptimisticRead()); |
757 |
< |
waitForThreadToEnterWaitState(t); |
757 |
> |
assertThreadBlocks(t, Thread.State.WAITING); |
758 |
|
t.interrupt(); |
759 |
|
awaitTermination(t); |
760 |
|
assertTrue(lock.isWriteLocked()); |
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 |
+ |
|
1230 |
+ |
/** Tries out sample usage code from StampedLock javadoc. */ |
1231 |
+ |
public void testSampleUsage() throws Throwable { |
1232 |
+ |
class Point { |
1233 |
+ |
private double x, y; |
1234 |
+ |
private final StampedLock sl = new StampedLock(); |
1235 |
+ |
|
1236 |
+ |
void move(double deltaX, double deltaY) { // an exclusively locked method |
1237 |
+ |
long stamp = sl.writeLock(); |
1238 |
+ |
try { |
1239 |
+ |
x += deltaX; |
1240 |
+ |
y += deltaY; |
1241 |
+ |
} finally { |
1242 |
+ |
sl.unlockWrite(stamp); |
1243 |
+ |
} |
1244 |
+ |
} |
1245 |
+ |
|
1246 |
+ |
double distanceFromOrigin() { // A read-only method |
1247 |
+ |
double currentX, currentY; |
1248 |
+ |
long stamp = sl.tryOptimisticRead(); |
1249 |
+ |
do { |
1250 |
+ |
if (stamp == 0L) |
1251 |
+ |
stamp = sl.readLock(); |
1252 |
+ |
try { |
1253 |
+ |
// possibly racy reads |
1254 |
+ |
currentX = x; |
1255 |
+ |
currentY = y; |
1256 |
+ |
} finally { |
1257 |
+ |
stamp = sl.tryConvertToOptimisticRead(stamp); |
1258 |
+ |
} |
1259 |
+ |
} while (stamp == 0); |
1260 |
+ |
return Math.hypot(currentX, currentY); |
1261 |
+ |
} |
1262 |
+ |
} |
1263 |
+ |
|
1264 |
+ |
Point p = new Point(); |
1265 |
+ |
p.move(3.0, 4.0); |
1266 |
+ |
assertEquals(5.0, p.distanceFromOrigin()); |
1267 |
+ |
} |
1268 |
+ |
|
1269 |
|
} |