繁体   English   中英

线程安全地重置对象的引用

[英]Thread-safe resetting of an object's reference

someParameters hashmap每隔20分钟由一个线程加载一个.csv文件,并由setParameters方法设置

调用getParameters的多个线程经常读取它:执行一个值到相应值的查找转换。

代码是否不安全和/或“错误”的方式来实现这一点(特别是在性能方面)? 我知道ConcurrentHashMap,但我试图对并发性有一个更基本的理解,而不是使用继承线程安全的类。

我看到的一个潜在风险是,对象引用someParameters可以被重置,而另一个线程正在读取副本,因此另一个线程可能没有最新的值(这对我来说无关紧要)。

public class ConfigObject {
    private static HashMap<String, String> someParameters = new HashMap<String, String>();

    public HashMap<String, String> getParameters(){
        return new HashMap<String, String>(someParameters);
        //to some thread which will only ever iterate or get
    }

    public void setParameters(HashMap<String, String> newParameters){
        //could be called by any thread at any time
        someParameters = newParameters;
    }
}

这里有两个问题

  1. 可见性问题,因为更新后的someParameters可能对其他线程不可见,要修复此标记someParametersvolatile
  2. 其他问题是性能因为在get方法中创建新的HashMap,修复使用Utility方法Collections.unmodifiableMap()这只是包装原始地图并禁止put / remove方法。

如果我正确理解您的问题,您需要立即更改/替换许多参数(原子地)。 不幸的是, ConcurrentHashMap不支持原子批量插入/更新。

要实现此目的,您应该使用共享的ReadWriteLock 优势比较Collections.synchronized...并发读取,可以同时进行 :如果readLock从某个线程获取readLock().lock()从另一个线程调用不会阻塞。

ReadWriteLock lock = new ReadWriteLock();

// on write:
lock.writeLock().lock();
try {
   // write/update operation, 
   // e. g. clear map and write new values
} finally {
   lock.writeLock().unlock();
}

// on read:
lock.readLock().lock();
try {
   // read operation
} finally {
   lock.readLock().unlock();
}

暂无
暂无

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

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