【发布时间】:2016-12-13 17:54:00
【问题描述】:
在尝试使用ReentrantReadWriteLock 控制对具有许多不同读写操作的相当复杂的数据结构的访问时,我遇到了一些密切相关的问题。根据文档中的示例,我已经获取了一个读取和写入锁,并且我正在使用它们(据我所知)成功管理对该数据结构的并发访问。然而,在调试另一个问题时,我注意到有时我在同一个线程中获得了多个读锁。其基本原因是我有许多复杂的查询会调用更简单的查询(请参见下面的示例)。复杂查询可以被认为是一个事务,即在getVersion() 和myQuery 中对data 的访问之间不应该有写入。这个当前的解决方案有效,但这意味着在代码中的某些地方,我将拥有同一个线程拥有的多个读锁。我注意到写等效项有一个isHeldByCurrentThread() 方法,但奇怪的是readLock 中没有。我找不到以下内容:
- 在同一个线程中拥有多个读锁是不是很糟糕(风格不佳、性能不佳或存在未来错误的风险)?
- 使用
WriteLock.isHeldByCurrentThread来检查错误是不好的(例如,期望写锁但不存在,或者作为释放写锁的条件)? - 如果这是一个问题,是否有最佳实践来决定如何进行?我是否将
lockedAquired布尔值传递给可能从已经拥有锁的代码中调用的方法,我是否确保它们是唯一获取的,还是应该使用ReadLock.tryLock()?
这是代码示例:
public class GraphWorldModel {
//unfair RW Lock (default, see javadoc)
protected final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(false);
protected final ReentrantReadWriteLock.ReadLock readLock = rwl.readLock();
protected final ReentrantReadWriteLock.WriteLock writeLock = rwl.writeLock();
protected long versionID = 0;
protected Object data = null;
@Override
public long getVersion() {
long result = -1;
readLock.lock();
try {
result = this.versionID;
} finally {
readLock.unlock();
}
return result;
}
public ResultObject myQuery() {
//do some work
readLock.lock();
try {
long version = getVersion();
ResultObject result = new ResultObject(this.data, version);
//note: querying version and result should be atomic!
} finally {
readLock.unlock();
}
//do some more work
return result;
}
}
【问题讨论】:
-
锁,顾名思义,是可重入的。因此,当您已经拥有它时再次获得它根本不是问题。你所拥有的一切都很好。
标签: java multithreading concurrency reentrantreadwritelock