someParameters 哈希地图每隔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;
}
}
答案 0 :(得分:2)
这里有两个问题
someParameters
可能对其他线程不可见,要将此标记someParameters
修复为volatile
。Collections.unmodifiableMap()
这只是包装原始地图并禁止使用put / remove方法。答案 1 :(得分:1)
如果我正确理解您的问题,您需要立即更改/替换许多参数(原子地)。不幸的是,ConcurrentHashMap
不支持原子批量插入/更新。
要实现此目的,您应该使用共享ReadWriteLock
。与Collections.synchronized...
相比的优势是并发读取可以同时执行:如果从某个线程获取readLock
,则从另一个线程调用的readLock().lock()
将不会阻塞。 / p>
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();
}