我有一个服务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()){}
检查锁是否已锁定并等待解锁。这个解决方案似乎很脏。有更好的解决方案吗?
谢谢你。菲尔答案 0 :(得分:1)
我建议ReadWriteLock。 有了它,您可以根据需要多次阅读,只要未锁定读锁定。
@Service
public class MyService {
private Map<Key,Value> cache = null;
private ReentrantLock reentrantLock = new ReentrantLock();
public void rebuildCache(){
try {
reentrantLock.writeLock().lock();
cache = new ConcurrentHashMap<>();
... //processing time consuming stuff and building up the cache
}finally {
reentrantLock.writeLock().unlock();
}
}
public Value getValue(Key key){
if(reentrantLock.getReadLock().lock()){
return cache.get(key);
}finally{
reentrantLock.getReadLock().unlock();
}
}
...
}
答案 1 :(得分:1)
改为使用ReentrantReadWriteLock
。
在你的写作方法中:
theLock.writeLock().lock();
try {
// update the map
} finally {
theLock.writeLock().unlock();
}
在read方法中,请改用.readLock()。
然而,问题是在更新地图期间,所有读者都将被阻止;另一个解决方案是使用普通锁定将旧地图的引用替换为新的更新的地图,并使用普通的synchronized
。
更重要的是,你使用锁是不正确的。你应该这样做:
theLock.lock();
try {
// whatever
} finally {
theLock.unlock();
}
想象一下,如果锁定因当前锁定而失败会发生什么:您将始终尝试解锁,最终会得到IllegalLockStateException
。