使用パターンは、次の理由から生じました。
条件付きでデータが存在しない場合、データを待機するために読み取りスレッドが必要です。
読み取りロックは条件をサポートしていないため、条件は書き込みロックから取得する必要があります。
読み取りスレッドは状態を待機するため、待機するために書き込みロックも取得する必要があります。
クラスに次のロック定義があります。
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
protected final Lock readLock = rwl.readLock();
protected final Lock writeLock = rwl.writeLock();
protected final Condition hasData = writeLock.newCondition();
私のライターメソッドには、次のパターンがあります。
try {
writeLock.lock();
//...
if( something_written ) {
hasData.signalAll();
}
}
finally {
writeLock.unlock();
}
私の読み取り方法では、次のパターンがあります
try {
readLock.lock();
while( data_absent ) {
// I need to acquire write lock to wait for condition!
try {
// first releasing read lock since we can't acquire write lock otherwise
// unfortunately this won't release a lock if it was acquired more than once (reentrant)
readLock.unlock();
// acquiring write lock to wait it's condition
writeLock.lock();
hasData.await(1000, TimeUnit.MILLISECONDS);
}
finally {
// releasing write lock back
writeLock.unlock();
// reacquiring read lock
// again see note about reentrancy
readLock.lock();
}
}
// reading
}
finally {
readLock.unlock();
}
上記のパターンは正しいですか?
問題は、reader が再入可能である場合、つまり 2 回以上読み取りをロックしている場合、解放コードが機能せず、reader が書き込みロックを取得する行でハングすることです。