Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
spring框架中集合的Java可能竞争条件_Java_Spring_Multithreading_Race Condition - Fatal编程技术网

spring框架中集合的Java可能竞争条件

spring框架中集合的Java可能竞争条件,java,spring,multithreading,race-condition,Java,Spring,Multithreading,Race Condition,我正在使用tomcat下的spring框架来编写能够处理多个并发请求的服务。在我的服务类中声明了一个静态变量,该变量将在所有线程之间共享,并由读写锁保护。定期读取和写入此静态集合。每次更新时,我都会获得写锁,当我读取它时,我会获得读锁 存储在集合中的数据是来自数据库表的条目。所以它是一个类型列表的集合。基本上,我有一个很少更新的表,所以我将它缓存在进程内存中 现在,有时我需要记录这些数据,这样我就可以在不获取方法中的锁的情况下记录返回对象。还是会导致比赛状态?日志记录用于调试 此外,集合的返回值

我正在使用tomcat下的spring框架来编写能够处理多个并发请求的服务。在我的服务类中声明了一个静态变量,该变量将在所有线程之间共享,并由读写锁保护。定期读取和写入此静态集合。每次更新时,我都会获得写锁,当我读取它时,我会获得读锁

存储在集合中的数据是来自数据库表的条目。所以它是一个类型列表的集合。基本上,我有一个很少更新的表,所以我将它缓存在进程内存中

现在,有时我需要记录这些数据,这样我就可以在不获取方法中的锁的情况下记录返回对象。还是会导致比赛状态?日志记录用于调试

此外,集合的返回值是只读的,不被任何方法修改。服务对象之外没有人使用此集合

我觉得这应该行得通,因为当分配一个新集合时,只有当所有对它的引用都消失时,旧集合才会消失。在更新时,在解锁写锁之前,不允许对旧对象或新对象的新引用

代码如下所示:

class ObjService {
    
    private static Collection<OtherObj> _staticCollection;
    private static ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock(true);
    
    private Collection<OtherObj> getCollection () {
       Collection<OtherObj> retVal = null;

       rwlock.readLock().lock();
       if (_staticCollection != null) {
         retVal = _staticCollection;
         rwlock.readLock().unlock();
         log (retVal);
       }
       else {
          rwlock.readLock().unlock();
          ReloadCollectionFromDB ();
          rwlock.readLock().lock();
          retVal = _staticCollection;
          rwlock.readLock().unlock();
       }
    }

    private ReloadCollectionFromDB  () {
      Collection<OtherObj> otherObjCol = null;

      try {
         otherObjCol = objRepo.findAll ();
      }
      catch (Exception ex) {
         // log exception
         return;
      }

      rwlock.writeLock().lock();
      _staticCollection = otherObjCol;
      rwlock.writeLock().unlock();
    }


    // periodically get data from DB
    @Scheduled(initialDelayString = "120000", fixedDelayString = "540000")
    void readLoadCache () {
       ReloadCollectionFromDB ();
    }
}
class对象服务{
私有静态集合_staticCollection;
私有静态ReentrantReadWriteLock rBlock=新的ReentrantReadWriteLock(true);
私有集合getCollection(){
集合retVal=null;
rwlock.readLock().lock();
if(_staticCollection!=null){
retVal=_staticCollection;
rwlock.readLock().unlock();
日志(retVal);
}
否则{
rwlock.readLock().unlock();
重新加载CollectionFromDB();
rwlock.readLock().lock();
retVal=_staticCollection;
rwlock.readLock().unlock();
}
}
私有重载从DB()收集{
集合otherObjCol=null;
试一试{
otherObjCol=objRepo.findAll();
}
捕获(例外情况除外){
//日志异常
返回;
}
rwlock.writeLock().lock();
_staticCollection=otherObjCol;
rwlock.writeLock().unlock();
}
//定期从数据库中获取数据
@已计划(initialDelayString=“120000”,fixedDelayString=“540000”)
void readLoadCache(){
重新加载CollectionFromDB();
}
}
如果有更好的方法,我希望能得到一些指导

非常感谢,,
~Ash

基本上,记录日志需要读取集合,因此需要锁定readLock才能安全地执行此操作。如果您不依赖于具体的集合类型,并且一般无法回答,那么可能会出现什么问题。另外,您在
getCollection()
方法中到底想要实现什么?本地
retVal
变量的第二个赋值没有任何效果,这只是为了调试吗?我刚才所说的适用于可变集合-我假设集合不是不变的。看起来您目前只保护引用的分配—如果集合可以由其他线程修改(添加、删除或修改元素),这是不够的。调用方可以修改返回值是正确的,但此方法是私有的,所有调用方都将其用于只读。日志记录仅用于调试目的。在方法
getCollection()
中,第一个赋值用于集合不为null时,第二个赋值在集合首次初始化之后。