gpt4 book ai didi

java - 为什么不允许 ReadWriteLock 升级?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:24:15 27 4
gpt4 key购买 nike

ReadWriteLock 降级被 ReentrantReadWriteLock 实现所允许(下例中的 tryLock() 总是返回 true) :

void downgrade(final ReadWriteLock readWriteLock) {
boolean downgraded = false;
readWriteLock.writeLock().lock();
try {
// Always true, as we already hold a W lock.
final boolean readLockAcquired = readWriteLock.readLock().tryLock();
if (readLockAcquired) {
// Now holding both a R and a W lock.
assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 1;
assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 1;

readWriteLock.writeLock().unlock();
downgraded = true;
try {
// Now do some work with only a R lock held
} finally {
readWriteLock.readLock().unlock();

assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 0;
assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 0;
}
}
} finally {
if (!downgraded) {
// Never (we were holding a W lock while trying a R lock).
readWriteLock.writeLock().unlock();
}
assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 0;
assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 0;
}
}

不允许以类似方式进行锁升级背后的想法是什么?下面的 Write 锁的 tryLock() 方法可以安全地返回 true,在没有其他线程持有锁的情况下没有死锁的风险阅读锁:

void upgrade(final ReadWriteLock readWriteLock) {
readWriteLock.readLock().lock();
try {
// Always false: lock upgrade is not allowed
final boolean writeLockAcquired = readWriteLock.writeLock().tryLock();
// ...
} finally {
readWriteLock.readLock().unlock();
}
}

最佳答案

首先,请注意升级和降级在ReadWriteLock 的语义复杂性方面并不等同。

您不需要抵制争用来完成降级事务,因为您已经拥有锁上升级最多的权限,并且因为您保证是当前执行降级的唯一线程。升级则不同,因此支持升级的机制自然需要更复杂(或更智能)。

要可用,升级机制需要防止死锁,以防两个读取线程同时尝试升级(或专门针对 ReentrantReadWriteLock,以防持有多个读取锁的单个读取线程尝试升级) .此外,该机制需要指定如何处理失败的升级请求(其读锁是否会失效),这就更重要了。

正如您现在可能看到的那样,在 ReentrantReadWriteLock 中完全处理这些问题至少可以说是不方便的(不过,这是 .NET 的 ReaderWriterLock 尝试的,我认为实际上成功地做到了)。我的猜测是,虽然 final boolean writeLockAcquired = readWriteLock.writeLock().tryLock(); 可以在一些微不足道的情况下取得成功,但可升级性仍然不够好,无法普遍使用- 在足够激烈的争用下,如果你输掉了写锁的竞争,你就在同一条船上,就好像你解锁了读锁并试图获得写锁(给其他人偷偷摸摸并获取写锁的机会之间)。

提供锁可升级性的一个好方法是只允许一个线程尝试升级 - 这就是 ReentrantReadWriteUpdateLock .NET 的 ReaderWriterLockSlim 的作用或作用做。但是我仍然会推荐 Java 8 的 StampedLock 作为:

  • 在低竞争下,它的乐观读取比使用读取锁快得多
  • 它的 API 对升级的限制要少得多(从乐观读到读锁再到写锁)
  • 我尝试创建一个现实的 JMH 基准测试,其中一个其他类似的锁击败它几乎总是失败

关于java - 为什么不允许 ReadWriteLock 升级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33342593/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com