繁体   English   中英

使用ReentrantReadWriteLock和一个布尔标志

[英]Using ReentrantReadWriteLock and a boolean flag

我有一个缓存,该缓存预先由大量数据(通过后台线程)加载,并且直到满时才可用(它还会经常重新加载,并且在该加载期间不可用)。 我希望使用它的类在访问之前检查标志isLoaded() 我使用ReentrantReadWriteLock(为简单起见,在代码中省略了它)来进行访问控制,如下所示:

public class Cache {

   private volatile boolean loaded = false; //starts false

   private static String[] cache;

   private static Lock readLock;
   private static Lock writeLock;

   public Object get(Object key) {
       if (!readLock.tryLock()) throw IllegalStateException(...);
       try {
           ... do some work
       } finally {
           readLock.unlock();
       }
   }

   // called by background thread
   private void loadFull() {
      loaded = false;
      writeLock.lock()
      try {
          cache = new String[];
          ... fill cache
      } finally {
          writeLock.unlock();
          loaded = true;
      }
   }
....
}  

现在在另一堂课中,我有一个像这样的块:

if (cache.isLoaded()) {
    try {
      Object x = cache.get(y);
    } catch (IllegalStateException iex) {
      // goto database for object
    }
} else {
    // goto database for object
}

我真的需要try/catch吗? 是否有可能将标志设置为false并且readLock try()将失败? 我是否应该还要烦恼该标志并突出捕获Exception(因为如果抛出Exception就像标志为false一样,我基本上会执行相同的代码)。 我只是觉得自己做错了点什么,但我不能指责它。 谢谢。

我真的需要try / catch吗? 是否有可能将标志设置为false并且readLock try()将失败?

是的,您需要它。 cache.isLoaded()cache.get()的时间之间,编写者可以进入并获得写锁-在这种情况下, cache.isLoaded()将返回true ,但是cache.get()将引发异常。

我是否应该还要烦恼该标志并突出捕获Exception(因为如果抛出Exception就像标志为false一样,我基本上会执行相同的代码)。

从显示的代码中,仅在get无法获取读取锁的情况下才会引发异常。 仅当同时存在并发写入器时,读取锁定的获取失败。 在这种情况下, isLoaded也将返回false。 因此,仅依靠异常就足够了。 另外,考虑创建专门的CacheStaleException

如果其他某个线程已经获取了该锁,则tryLock将失败。 这通常意味着,如果客户端由于争用率较高(多个客户端访问同一缓存)而无法获取锁,则会引发异常。 您在客户端层实施了任何可解决此类情况的后备策略吗?

另外,为什么要使用static锁? 我认为,即使您的缓存通常在应用程序中作为单例使用,也无需通过将Locks设置为静态来限制其可用性。

不,但是老实说,您的范例令人困惑。 假定转到实际数据库很昂贵,这就是缓存的目的。 在重新加载缓存的情况下,仅等待直到重新缓存就更好了吗?

假设您确实确实想在读取锁不立即可用的情况下转到数据库,我可以这样做:

   public Object get(Object key) {
       Object returnValue;
       if (readLock.tryLock()) {
           try {
               ... do some work
               returnValue = ...
           } finally {
               readLock.unlock();
           }
       } else {
           //go to database
           returnValue = ...
       }
       return returnValue;
   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM