我有: Map<K1, Map<K2, V>>
,其中:
我想: 让地图并发。我想同时:
更新的问题: 代码是否容易出错?
public class V {
K1 k1;
K2 k2;
final ConcurrentHashMap<K1, ConcurrentHashMap<K2, V>> map = new ConcurrentHashMap<K1, ConcurrentHashMap<K2, V>> ();
public void changeK1(V v, K1 newK) {
removeValue(v); //doesn't remove old val!
v.k1 = newK; //PROBLEM: map is the same as before `removeValue` call, but it shouldn't!
addValue(V); //doesn't add new val!
}
void addValue(V v) {
if (map.get(v.k1) == null) {
map.put(v.k1, new ConcurrentHashMap<K2, V>());
}
map.get(v.k1).put(v.k2, v);
}
void removeValue(V v) {
ConcurrentHashMap<v.k2, v> subMap = map.get(v.k1);
if (subMap != null) {
subMap.remove(v.k2); //remove from subMap but doesn't remove from map!
}
}
//also I can remove any value by K1 or K2 at any moment!
}
答案 0 :(得分:1)
此代码受竞争条件限制。
多个线程可以检测到map.get(v.k1) == null
。根据执行顺序,其中一个线程可以为k1
分配一个新的子图,并为其他线程已添加其值的子图执行clobber。
ConcurrentMap
的一个更突出的功能是putIfAbsent()
方法。
map.putIfAbsent(v.k1, new ConcurrentHashMap<>());
map.get(v.k1).put(v.k2, v);