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 static java.util.concurrent.locks.StampedLock.isLockStamp; |
12 |
> |
import static java.util.concurrent.locks.StampedLock.isOptimisticReadStamp; |
13 |
> |
import static java.util.concurrent.locks.StampedLock.isReadLockStamp; |
14 |
> |
import static java.util.concurrent.locks.StampedLock.isWriteLockStamp; |
15 |
|
|
16 |
|
import java.util.ArrayList; |
17 |
|
import java.util.List; |
252 |
|
long s = assertNonZero(lock.writeLock()); |
253 |
|
assertTrue(lock.validate(s)); |
254 |
|
assertFalse(lock.validate(lock.tryWriteLock())); |
255 |
< |
assertFalse(lock.validate(lock.tryWriteLock(0L, SECONDS))); |
255 |
> |
assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(), |
256 |
> |
randomTimeUnit()))); |
257 |
|
assertFalse(lock.validate(lock.tryReadLock())); |
258 |
< |
assertFalse(lock.validate(lock.tryReadLock(0L, SECONDS))); |
258 |
> |
assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(), |
259 |
> |
randomTimeUnit()))); |
260 |
|
assertFalse(lock.validate(lock.tryOptimisticRead())); |
261 |
|
lock.unlockWrite(s); |
262 |
|
} |
587 |
|
long s = lock.readLock(); |
588 |
|
Thread t = newStartedThread(new CheckedRunnable() { |
589 |
|
public void realRun() { |
590 |
< |
threadAssertEquals(0L, lock.tryWriteLock()); |
590 |
> |
assertEquals(0L, lock.tryWriteLock()); |
591 |
|
}}); |
592 |
|
|
593 |
|
awaitTermination(t); |
1185 |
|
} |
1186 |
|
assertUnlocked(lock); |
1187 |
|
} |
1188 |
+ |
|
1189 |
+ |
/** |
1190 |
+ |
* Stamped locks are not reentrant. |
1191 |
+ |
*/ |
1192 |
+ |
public void testNonReentrant() throws InterruptedException { |
1193 |
+ |
final StampedLock lock = new StampedLock(); |
1194 |
+ |
long stamp; |
1195 |
+ |
|
1196 |
+ |
stamp = lock.writeLock(); |
1197 |
+ |
assertValid(lock, stamp); |
1198 |
+ |
assertEquals(0L, lock.tryWriteLock(0L, DAYS)); |
1199 |
+ |
assertEquals(0L, lock.tryReadLock(0L, DAYS)); |
1200 |
+ |
assertValid(lock, stamp); |
1201 |
+ |
lock.unlockWrite(stamp); |
1202 |
+ |
|
1203 |
+ |
stamp = lock.tryWriteLock(1L, DAYS); |
1204 |
+ |
assertEquals(0L, lock.tryWriteLock(0L, DAYS)); |
1205 |
+ |
assertValid(lock, stamp); |
1206 |
+ |
lock.unlockWrite(stamp); |
1207 |
+ |
|
1208 |
+ |
stamp = lock.readLock(); |
1209 |
+ |
assertEquals(0L, lock.tryWriteLock(0L, DAYS)); |
1210 |
+ |
assertValid(lock, stamp); |
1211 |
+ |
lock.unlockRead(stamp); |
1212 |
+ |
} |
1213 |
+ |
|
1214 |
+ |
/** |
1215 |
+ |
* """StampedLocks have no notion of ownership. Locks acquired in |
1216 |
+ |
* one thread can be released or converted in another.""" |
1217 |
+ |
*/ |
1218 |
+ |
public void testNoOwnership() throws Throwable { |
1219 |
+ |
ArrayList<Future<?>> futures = new ArrayList<>(); |
1220 |
+ |
for (Function<StampedLock, Long> writeLocker : writeLockers()) |
1221 |
+ |
for (BiConsumer<StampedLock, Long> writeUnlocker : writeUnlockers()) { |
1222 |
+ |
StampedLock lock = new StampedLock(); |
1223 |
+ |
long stamp = writeLocker.apply(lock); |
1224 |
+ |
futures.add(cachedThreadPool.submit(new CheckedRunnable() { |
1225 |
+ |
public void realRun() { |
1226 |
+ |
writeUnlocker.accept(lock, stamp); |
1227 |
+ |
assertUnlocked(lock); |
1228 |
+ |
assertFalse(lock.validate(stamp)); |
1229 |
+ |
}})); |
1230 |
+ |
} |
1231 |
+ |
for (Future<?> future : futures) |
1232 |
+ |
assertNull(future.get()); |
1233 |
+ |
} |
1234 |
+ |
|
1235 |
+ |
/** Tries out sample usage code from StampedLock javadoc. */ |
1236 |
+ |
public void testSampleUsage() throws Throwable { |
1237 |
+ |
class Point { |
1238 |
+ |
private double x, y; |
1239 |
+ |
private final StampedLock sl = new StampedLock(); |
1240 |
+ |
|
1241 |
+ |
void move(double deltaX, double deltaY) { // an exclusively locked method |
1242 |
+ |
long stamp = sl.writeLock(); |
1243 |
+ |
try { |
1244 |
+ |
x += deltaX; |
1245 |
+ |
y += deltaY; |
1246 |
+ |
} finally { |
1247 |
+ |
sl.unlockWrite(stamp); |
1248 |
+ |
} |
1249 |
+ |
} |
1250 |
+ |
|
1251 |
+ |
double distanceFromOrigin() { // A read-only method |
1252 |
+ |
double currentX, currentY; |
1253 |
+ |
long stamp = sl.tryOptimisticRead(); |
1254 |
+ |
do { |
1255 |
+ |
if (stamp == 0L) |
1256 |
+ |
stamp = sl.readLock(); |
1257 |
+ |
try { |
1258 |
+ |
// possibly racy reads |
1259 |
+ |
currentX = x; |
1260 |
+ |
currentY = y; |
1261 |
+ |
} finally { |
1262 |
+ |
stamp = sl.tryConvertToOptimisticRead(stamp); |
1263 |
+ |
} |
1264 |
+ |
} while (stamp == 0); |
1265 |
+ |
return Math.hypot(currentX, currentY); |
1266 |
+ |
} |
1267 |
+ |
|
1268 |
+ |
double distanceFromOrigin2() { |
1269 |
+ |
long stamp = sl.tryOptimisticRead(); |
1270 |
+ |
try { |
1271 |
+ |
retryHoldingLock: |
1272 |
+ |
for (;; stamp = sl.readLock()) { |
1273 |
+ |
if (stamp == 0L) |
1274 |
+ |
continue retryHoldingLock; |
1275 |
+ |
// possibly racy reads |
1276 |
+ |
double currentX = x; |
1277 |
+ |
double currentY = y; |
1278 |
+ |
if (!sl.validate(stamp)) |
1279 |
+ |
continue retryHoldingLock; |
1280 |
+ |
return Math.hypot(currentX, currentY); |
1281 |
+ |
} |
1282 |
+ |
} finally { |
1283 |
+ |
if (StampedLock.isReadLockStamp(stamp)) |
1284 |
+ |
sl.unlockRead(stamp); |
1285 |
+ |
} |
1286 |
+ |
} |
1287 |
+ |
|
1288 |
+ |
void moveIfAtOrigin(double newX, double newY) { |
1289 |
+ |
long stamp = sl.readLock(); |
1290 |
+ |
try { |
1291 |
+ |
while (x == 0.0 && y == 0.0) { |
1292 |
+ |
long ws = sl.tryConvertToWriteLock(stamp); |
1293 |
+ |
if (ws != 0L) { |
1294 |
+ |
stamp = ws; |
1295 |
+ |
x = newX; |
1296 |
+ |
y = newY; |
1297 |
+ |
return; |
1298 |
+ |
} |
1299 |
+ |
else { |
1300 |
+ |
sl.unlockRead(stamp); |
1301 |
+ |
stamp = sl.writeLock(); |
1302 |
+ |
} |
1303 |
+ |
} |
1304 |
+ |
} finally { |
1305 |
+ |
sl.unlock(stamp); |
1306 |
+ |
} |
1307 |
+ |
} |
1308 |
+ |
} |
1309 |
+ |
|
1310 |
+ |
Point p = new Point(); |
1311 |
+ |
p.move(3.0, 4.0); |
1312 |
+ |
assertEquals(5.0, p.distanceFromOrigin()); |
1313 |
+ |
p.moveIfAtOrigin(5.0, 12.0); |
1314 |
+ |
assertEquals(5.0, p.distanceFromOrigin2()); |
1315 |
+ |
} |
1316 |
+ |
|
1317 |
+ |
/** |
1318 |
+ |
* Stamp inspection methods work as expected, and do not inspect |
1319 |
+ |
* the state of the lock itself. |
1320 |
+ |
*/ |
1321 |
+ |
public void testStampStateInspectionMethods() { |
1322 |
+ |
StampedLock lock = new StampedLock(); |
1323 |
+ |
|
1324 |
+ |
assertFalse(isWriteLockStamp(0L)); |
1325 |
+ |
assertFalse(isReadLockStamp(0L)); |
1326 |
+ |
assertFalse(isLockStamp(0L)); |
1327 |
+ |
assertFalse(isOptimisticReadStamp(0L)); |
1328 |
+ |
|
1329 |
+ |
{ |
1330 |
+ |
long stamp = lock.writeLock(); |
1331 |
+ |
for (int i = 0; i < 2; i++) { |
1332 |
+ |
assertTrue(isWriteLockStamp(stamp)); |
1333 |
+ |
assertFalse(isReadLockStamp(stamp)); |
1334 |
+ |
assertTrue(isLockStamp(stamp)); |
1335 |
+ |
assertFalse(isOptimisticReadStamp(stamp)); |
1336 |
+ |
if (i == 0) |
1337 |
+ |
lock.unlockWrite(stamp); |
1338 |
+ |
} |
1339 |
+ |
} |
1340 |
+ |
|
1341 |
+ |
{ |
1342 |
+ |
long stamp = lock.readLock(); |
1343 |
+ |
for (int i = 0; i < 2; i++) { |
1344 |
+ |
assertFalse(isWriteLockStamp(stamp)); |
1345 |
+ |
assertTrue(isReadLockStamp(stamp)); |
1346 |
+ |
assertTrue(isLockStamp(stamp)); |
1347 |
+ |
assertFalse(isOptimisticReadStamp(stamp)); |
1348 |
+ |
if (i == 0) |
1349 |
+ |
lock.unlockRead(stamp); |
1350 |
+ |
} |
1351 |
+ |
} |
1352 |
+ |
|
1353 |
+ |
{ |
1354 |
+ |
long optimisticStamp = lock.tryOptimisticRead(); |
1355 |
+ |
long readStamp = lock.tryConvertToReadLock(optimisticStamp); |
1356 |
+ |
long writeStamp = lock.tryConvertToWriteLock(readStamp); |
1357 |
+ |
for (int i = 0; i < 2; i++) { |
1358 |
+ |
assertFalse(isWriteLockStamp(optimisticStamp)); |
1359 |
+ |
assertFalse(isReadLockStamp(optimisticStamp)); |
1360 |
+ |
assertFalse(isLockStamp(optimisticStamp)); |
1361 |
+ |
assertTrue(isOptimisticReadStamp(optimisticStamp)); |
1362 |
+ |
|
1363 |
+ |
assertFalse(isWriteLockStamp(readStamp)); |
1364 |
+ |
assertTrue(isReadLockStamp(readStamp)); |
1365 |
+ |
assertTrue(isLockStamp(readStamp)); |
1366 |
+ |
assertFalse(isOptimisticReadStamp(readStamp)); |
1367 |
+ |
|
1368 |
+ |
assertTrue(isWriteLockStamp(writeStamp)); |
1369 |
+ |
assertFalse(isReadLockStamp(writeStamp)); |
1370 |
+ |
assertTrue(isLockStamp(writeStamp)); |
1371 |
+ |
assertFalse(isOptimisticReadStamp(writeStamp)); |
1372 |
+ |
if (i == 0) |
1373 |
+ |
lock.unlockWrite(writeStamp); |
1374 |
+ |
} |
1375 |
+ |
} |
1376 |
+ |
} |
1377 |
+ |
|
1378 |
|
} |