简体   繁体   English

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

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

The someParameters hashmap is loaded from a .csv file every twenty minutes or so by one thread and set by the setParameters method. someParameters hashmap每隔20分钟由一个线程加载一个.csv文件,并由setParameters方法设置

It is very frequently read by multiple threads calling getParameters : to perform a lookup translation of one value into a corresponding value. 调用getParameters的多个线程经常读取它:执行一个值到相应值的查找转换。

Is the code unsafe and/ or the "wrong" way to achieve this (particularly in terms of performance)? 代码是否不安全和/或“错误”的方式来实现这一点(特别是在性能方面)? I know about ConcurrentHashMap but am trying to get a more fundamental understanding of concurrency, rather than using classes that are inherrently thread-safe. 我知道ConcurrentHashMap,但我试图对并发性有一个更基本的理解,而不是使用继承线程安全的类。

One potential risk I see is that the object reference someParameters could be reset whilst another thread is reading the copy, so the other thread might not have the latest values (which wouldn't matter to me). 我看到的一个潜在风险是,对象引用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;
    }
}

There are two problems here 这里有两个问题

  1. Visibility problem, as someParameters after update might not be visible to other thread, to fix this mark someParameters as volatile . 可见性问题,因为更新后的someParameters可能对其他线程不可见,要修复此标记someParametersvolatile
  2. Other problem is performance one due to creating new HashMap in get method, to fix that use Utility method Collections.unmodifiableMap() this just wrap original map and disallowing put/remove method. 其他问题是性能因为在get方法中创建新的HashMap,修复使用Utility方法Collections.unmodifiableMap()这只是包装原始地图并禁止put / remove方法。

If I understand your problem correctly, you need to change/replace many parameters at once (atomically). 如果我正确理解您的问题,您需要立即更改/替换许多参数(原子地)。 Unfortunately, ConcurrentHashMap doesn't support atomic bulk inserts/updates. 不幸的是, ConcurrentHashMap不支持原子批量插入/更新。

To achieve this, you should use shared ReadWriteLock . 要实现此目的,您应该使用共享的ReadWriteLock Advantage comparing to Collections.synchronized... is that concurrent reads can be performed simultaneously : if readLock is acquired from some thread, readLock().lock() called from another thread will not block. 优势比较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