【发布时间】:2014-02-24 17:09:10
【问题描述】:
我有: Map<K1, Map<K2, V>>,其中:
- K1 是可变的。 (它很少改变,而且只在一个地方改变,所以我可以删除 K1 的 Map 并用另一个键重新设置)
我想要: 使地图并发。我要同时:
- 修改 K2 的值 (V)
- 将整个地图替换为 K1
更新问题:下面的代码容易出错吗?
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!
}
【问题讨论】:
-
应该返回什么
map.get(null)? -
@nachokk 也是实体地图
-
在没有大量锁的情况下,很难实现嵌套可变数据结构的并发性。
-
另外,请注意
HashMap中键的可变性非常危险。如果对象发生变化,则不会重新计算地图中关键对象的位置。 -
(i) 可变键是个坏主意,在并发结构中更是如此 (ii) 默认替换 null
K1 NULL = new K1(someSpecificValue);
标签: java collections map concurrency