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();
}
ある種の遅延インテントのロックを許可しないようにする設計上の決定は何ですか? そのようなロックの設計には、単に私が気付いていない重大な問題がありますか?