如何使用StampedLock乐观锁定?(我无法理解来自java doc的代码示例)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用StampedLock乐观锁定?(我无法理解来自java doc的代码示例)相关的知识,希望对你有一定的参考价值。
最近我了解了StampedLock
的存在?
qazxsw指出我意识到它是改进的ReentrantReadWriteLock有一些差异:
- 不是可重入的
- 支持乐观锁定
- 支持从readLock升级到writeLock
我也从java中读过例子,但我不明白那段代码:
https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/locks/StampedLock.html
class Point {
private double x, y;
private final StampedLock sl = new StampedLock();
// a read-only method
// upgrade from optimistic read to read lock
double distanceFromOrigin() {
long stamp = sl.tryOptimisticRead();
try {
retryHoldingLock: for (;; stamp = sl.readLock()) {
if (stamp == 0L)
continue retryHoldingLock;
// possibly racy reads
double currentX = x;
double currentY = y;
if (!sl.validate(stamp))
continue retryHoldingLock;
return Math.hypot(currentX, currentY);
}
} finally {
if (StampedLock.isReadLockStamp(stamp))
sl.unlockRead(stamp);
}
}
}
是什么意思? [评论中的答案]
如果另一个线程读取possibly racy reads
或x
,这是一个问题吗? [评论中的答案]
为什么我们首先执行tryOptimisticRead并在tryOptimisticRead失败的情况下在for循环中执行readLock?什么逻辑?
为什么我们在解锁之前最终阻止了y
?
为什么我们首先执行tryOptimisticRead并在tryOptimisticRead失败的情况下在for循环中执行readLock?什么逻辑?
最好的情况是我们能够在不必获取锁定的情况下读取if (StampedLock.isReadLockStamp(stamp))
和x
。这并不意味着我们不建立一个先发生过的关系,它只是意味着我们不需要调用可能的阻塞动作。
y
给我们一个邮票价值。这个内部状态的tryOptimisticRead
读取确定在后续读取之后可以看到在该标记值的易失性写入之前写入的任何内容。这意味着,如果volatile
中返回的标记值在您阅读tryOptimisticRead
和x
时没有变化,那么另一次写入没有发生,我们拥有最新的值。但是,如果加盖的价值确实发生了变化,那么所有的赌注都会被取消,您需要保护自己,如下所述。
有可能,并且,根据您的用例,y
和x
可能会在执行y
的某个时刻发生变化。如果distanceFromOrigin
和x
改变,并且可能经常改变,那么你最终会想要成功。
y
是节目的方式,说“好吧,我放弃了,让我们以封锁的方式阅读它”。从理论上讲,你可以在最终调用readLock
之前将代码写入tryOptimisticRead
几次,但是如果readLock
和x
不断更新,你会想要给自己一个。
为什么我们有if(StampedLock.isReadLockStamp(stamp))里面最后阻止vbefore解锁?
如果调用y
,则必须在退出之前释放它,以便随后的readLock
可以获得锁定。如果你在writeLock
取得成功,你将不必释放tryOptimisticRead
,因为你从来没有需要获得它。
以上是关于如何使用StampedLock乐观锁定?(我无法理解来自java doc的代码示例)的主要内容,如果未能解决你的问题,请参考以下文章
CoreData:错误:无法解决乐观锁定失败:乐观锁定失败(null),只有旧记录,为啥?