【问题标题】:Better solution than while (reentrantLock.isLocked()) for waiting比 while (reentrantLock.isLocked()) 等待更好的解决方案
【发布时间】:2015-09-29 11:51:11
【问题描述】:

我有一个提供对 Map 的访问的服务 bean。有时我需要重建地图的内容,这需要几秒钟,我想在重建地图时阻止对地图的访问,因为它可以从不同的线程访问。

@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()){}

检查锁是否被锁定并等待解锁。这个解决方案似乎很脏。有没有更好的解决方案?

【问题讨论】:

标签: java concurrency locking


【解决方案1】:

请改用ReentrantReadWriteLock

在你的 write 方法中:

theLock.writeLock().lock();
try {
    // update the map
} finally {
    theLock.writeLock().unlock();

  }

在 read 方法中,使用 .readLock() 代替。

这有一个问题,但是在更新地图的过程中,所有的阅读器都会被屏蔽;另一种解决方案是使用普通锁将旧地图的引用替换为新的更新地图,并使用普通旧的synchronized


更重要的是,您对锁的使用不正确。你应该这样做:

theLock.lock();
try {
    // whatever
} finally {
    theLock.unlock();
}

想象一下,如果您当前的锁锁定失败会发生什么:您总是会尝试解锁,最终会得到IllegalLockStateException

【讨论】:

  • 好的,谢谢。这正是我一直在寻找的。也感谢您的第二个建议。
【解决方案2】:

我建议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();
    }
   }
   ...
}

【讨论】:

    猜你喜欢
    • 2011-05-05
    • 2012-03-31
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多