【发布时间】:2013-04-22 21:21:15
【问题描述】:
在Java 的实现锁中,没有办法将锁从读锁自动升级为写锁。比如下面的代码sn -p 失败
ReentrantReadWriteLock lock = new ...
lock.readLock().lock();
boolean mustWrite = false;
// do somestuff and determine you must instead write! :-O
if(mustWrite) {
lock.writeLock().lock();
writeSomeStuff();
lock.writeLock().unlock();
}
lock.readLock.unlock();
写锁获取必须等待所有读锁都完成,这样它才知道它不会覆盖读者可能正在读取的数据。那很糟。所以解决方法是做这样的事情:
if(mustWrite) {
lock.readLock().unlock(); // let go of read before writing
lock.writeLock().lock();
writeSomeStuff();
lock.writeLock().unlock();
lock.readLock().lock(); // get back to reading
}
但这并不理想 - 当您解锁读取并开始写入时,有人可能会去做一些事情。现在,无论如何仔细检查这些条件可能是个好主意,但仍然 - 它很丑。
现在,通常情况下,当您获取锁时,您希望强制代码等待它实际获取,然后再执行您正在执行的操作。您不想只相信您的锁定机制,它会在您开始弄乱数据之前为您提供锁定。
但是为什么它会强制你从你发出想要锁的信号到你真正被读取等待时停止执行呢?例如,为什么它不能允许这样的事情:
lock.writeLock().notifyIntentToLock(); // puts you in line to get the write lock
// everyone else will block until you both
// acquire and release the lock
lock.readLock().unlock(); // proceed with the unlock so you don't deadlock
lock.writeLock().makeGoodOnIntentToLock(); // actually acquire that lock
所以从某种意义上说,当前的锁功能可以被理论化为它们都是同时完成的,比如
public void lock() {
this.notifyIntentToLock();
this.makeGoodOnIntentToLock();
}
哪些设计决策会使它们不允许某种延迟意图锁定?这样的锁设计是否存在我根本看不到的严重问题?
【问题讨论】:
-
一种锁,让您无需等待即可保留它,并允许您稍后再查看,希望此时您已经获得它并且您不必再等待。我实际上认为这是一个非常好的主意。它可能具有比其他类型的锁更复杂的实现——我不确定。人们可能能够在较低级别的原语之上有效地实现它,就像在互斥锁和/或硬件比较和交换指令等更简单的原语之上实现读写器锁一样。
-
这里是新手,但这样的功能不会鼓励应用程序非常贪婪吗?例如,如果我知道稍后在我的程序中需要一个文件,我可能会在一开始就
notifyIntentToLock,拒绝任何其他应用程序访问它[可能]比实际需要的时间长得多。 -
@Supericy 好吧,他们当然可以。但他们已经可以做到这一点——他们可以一开始就打电话给
lock。因此,它不会引入任何新的诱惑来滥用已经不存在的 API。 -
@Celada,硬件比较和交换指令 - 一切都在它们之上实现 r LL/SC(加载链接/存储条件)替代方案。编写一个简单的 RW 锁实际上非常困难。 Java8 有 StampedLock,它的使用可能需要一个循环,但最重要的是它需要在 java 中添加 a load/load barrier 以使其正常工作。
标签: java locking reentrantreadwritelock