java - 带同步的 ConcurrentHashMap
问题描述
我正在维护一些遗留代码,并找到了一些带有synchronized
关键字 on 的实现ConcurrentHashMap
。对我来说似乎没有必要:
public class MyClass{
private final Map<MyObj, Map<String, List<String>>> conMap = new ConcurrentHashMap<>();
//...
//adding new record into conMap:
private void addToMap(MyObj id, String name, String value){
conMap.putIfAbsent(id, new ConcurrentHashMap<>());
Map<String, List<String>> subMap = conMap.get(id);
synchronized(subMap){ // <-- is it necessary?
subMap.putIfAbsent(name, new ArrayList<>());
subMap.get(name).add(value);
}
}
//...
public void doSomthing((MyObj id){
List<Map<String, List<String>>> mapsList = new LinkedList<>();
for(MyObj objId: conMap.keySet()){
if(objId.key1.equals(id.key1)){
mapsList.add(conMap.get(objId));
}
}
for(Map<String, List<String>> map: mapsList){
synchronized(map){ // <-- is it necessary?
if(timeout <= 0){
log(map.size());
for(List<String> value: map.values(){
log(id, value);
}
}
else{
int sum = 0;
for(map.Entry<String, List<String>> val: map.entrySet()){
sum += val.getValue().size();
}
log(sum);
map.wait(timeout);
}
}
//...
}
synchronized
那么,在已经并发的对象上使用 key 是否合理?或者这是两个不同的东西?
解决方案
这是有必要的,因为多个线程可能会尝试同时附加到同一个线程ArrayList
。synchonized
正在防止这种情况发生,因为显然ArrayList
不同步。
从 Java 8 开始,我们有了computeIfAbsent
这意味着他们正在执行的 put 和 get 可以被简化。我会这样写,不需要同步:
conMap.computeIfAbsent(id, k -> new ConcurrentHashMap<>())
.computeIfAbsent(name, k -> new CopyOnWriteArrayList<>()) // or other thread-safe list
.add(value);
推荐阅读
- android - Android Studio 在所有视图上显示错误
- javascript - 如何在单个绘制调用中渲染多个蒙皮网格?(三个J)
- position - 如何在 Yandex 地图中将所选点定位在地图顶部
- security - 在数据库泄露的情况下保护多个用户身份的匿名性
- java - 运行 java servlet 时获取 java.lang.ClassNotFoundException
- chart.js - chart.js 时间序列多轴案例
- python - 为什么在安装 pyxll 时出现此错误?
- python - 为“cudf”做“diff”的最有效方法是什么
- python - node进程和python子进程之间的双向通信
- java - 我在哪里放置我的资源文件以使其在 Spring 中使用类路径可读?