我有一个java线程安全映射,它存储String到Object映射:
ConcurrentHashMap<String, MyObject> map = new ConcurrentHashMap<>();
这里MyObject是用户定义的类。现在考虑以下方法:
public void replace(String key, MyObject o) {
MyObject m = map.get("somekey");
synchronized(m) {
// Modify some internal components of m
// and some other objects related to m
}
}
我的目的是希望通过不对整个类进行锁定来最大限度地提高性能,但仅限于尝试访问地图中相同键的线程。基本上每次在地图中替换一个条目(未添加)时,这部分代码就会被执行。类似的东西:
public void put(String key, MyObject o) {
if (map.putIfAbsent(key, o) == null){ //do something
}
else {
replace(key, o);
}
}
出于所有实际目的,我们可以假设这是可以更改对MyObject的引用的唯一方法。这个实现线程安全吗?
答案 0 :(得分:3)
以下实施线程是否安全?
如果您始终使用此MyObject
实例访问和修改同步块中的MyObject
的给定实例,则取决于您在代码中访问和修改MyObject
实例的方式作为对象的监视器,然后它是线程安全的,否则它不会。
您的put
方法不是线程安全的,因为putIfAbsent
并且replace
未执行原子,这可能会导致竞争条件问题,使用merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
执行完全相同的操作,但原子作为下一个:
public void put(String key, MyObject o) {
map.merge(
key, o,
(v1, v2) -> {
// Modify some internal components of v1
// and some other objects related to v1
return v2;
}
);
}