我有一个提供对 map 的访问的服务 bean。有时我需要重建 map 的内容,这需要几秒钟的时间,并且我想在重建时阻止对 map 的访问,因为可以从不同的线程访问它。
@Service
public class MyService {
private Map<Key,Value> cache = null;
private ReentrantLock reentrantLock = new ReentrantLock();
public void rebuildCache(){
try {
reentrantLock.lock();
cache = new ConcurrentHashMap<>();
... //processing time consuming stuff and building up the cache
}finally {
reentrantLock.unlock();
}
}
public Value getValue(Key key){
while (lock.isLocked()){}
return cache.get(key);
}
...
}
如你所见,我使用
while (reentrantLock.isLocked()){}
检查锁是否已锁定并等待其解锁。这个解决方案似乎很脏。有更好的解决办法吗?
最佳答案
改用ReentrantReadWriteLock
。
在您的写入方法中:
theLock.writeLock().lock();
try {
// update the map
} finally {
theLock.writeLock().unlock();
}
在 read 方法中,使用 .readLock() 代替。
但是这有一个问题,在 map 更新期间,所有读者都会被屏蔽;另一种解决方案是使用普通锁将旧映射的引用替换为新的、更新的映射,并使用普通的旧同步
。
更重要的是,您对锁的使用是不正确的。你应该这样做:
theLock.lock();
try {
// whatever
} finally {
theLock.unlock();
}
想象一下,如果当前锁定的锁定失败会发生什么:您将始终尝试解锁,最终会遇到 IllegalLockStateException
。
关于java - 比 while (reentrantLock.isLocked()) 等待更好的解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32843259/