使用可变键映射并发

时间:2014-02-24 17:09:11

标签: java collections map concurrency

我有: Map<K1, Map<K2, V>>,其中:

  1. K1是可变的。 (它变化很少,只有在不合适的位置,所以我可以删除K1的Map并用另一个键再次设置它)
  2. 我想: 让地图并发。我想同时:

    1. 修改K2的值(V)
    2. 替换K1的整个地图
    3. 更新的问题: 代码是否容易出错?

      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!
      }
      

1 个答案:

答案 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);