使用模式源于以下原因:
如果条件不存在,我需要读取线程来等待数据。
读锁不支持条件,所以条件应该取自写锁。
由于读线程会等待条件,它也应该获得写锁来等待。
我在课堂上有以下锁定义:
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();
}
上面的模式正确吗?
问题是如果读者是可重入的,即多次锁定读,则释放代码不起作用,读者在获得写锁的那一行挂起。