2

在 Java 的实现锁中,没有办法将锁从读锁自动升级为写锁。例如,以下代码片段失败

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();
}

什么样的设计决策会让他们不允许某种延迟的意图锁定?像我根本没有看到的那样的锁设计是否存在严重问题?

4

1 回答 1

0

在决定采用独占锁之后,您所要做的就是:

  • 离开读锁,
  • 获取写锁和
  • 再次检查条件
  • 根据结果​​,要么继续,要么退出。

至于取写锁的意图,当多个并发意图存在时会发生什么?可能他们所有人都必须检查初始条件,因为无法确定谁会成为受害者(在获胜者之后授予锁定)。

还有更多 - impl。RW 锁的启动很糟糕,因为读取会修改导致一致性流量的元数据 - 因此 RW 锁不能很好地扩展。

于 2014-05-26T20:45:47.147 回答