Java ConcurrentSkipListMap:原子地添加另一个Collection对象

时间:2011-12-15 14:57:33

标签: java data-structures collections concurrency synchronization

我有一个并发的场景,我必须在排序的数据结构上写很多东西。

我考虑过使用ConcurrentSkipListMap。我的定义是这样的:ConcurrentSkipListMap<K, List<V>>,当插入第一个元素时,当然很难管理List<V>的插入。

即:

List<V> list = map.get(k);
if (list == null) {
    list = new LinkedList<V>();
    map.put(list);
}
list.add(v);

当然这不是原子的。使用类putIfAbsent()方法会使它变得非常笨拙和低效:

List<V> newElement = new LinkedList<V>();
List<V> previous = map.putIfAbsent(k, newElement);
if (previous != null) {
    previous.add(v);
} else {
    newElement.add(v);
}

一种方法当然是创建我自己的锁并保护正常的TreeMap,但由于我对这个对象有很高的写入率,我更喜欢专门为它设计的东西。当然,像collections.defaultdict的python这样的东西是完美的。

1 个答案:

答案 0 :(得分:1)

一些事情。

首先:最有效的方法是处理你的假如缺席案例是进行伪双重检查

public void add(Object key, Object val) {
    List list = map.get(key);
    if (list == null) {
        list = new LinkedList();
        List temp = map.putIfAbsent(list);
        if (temp != null)
            list = temp;
    }
    list.add(val);
}

这就像你可以得到的那样有效的情况。

第二:在这里添加到列表仍然存在并发问题。您可能希望在放入地图之前将LinkedList包装在Collections.synchronizedList()中。

public void add(Object key, Object val) {
        List list = map.get(key);
        if (list == null) {
            list = Collections.synchronizedList(new LinkedList());
            List temp = map.putIfAbsent(list);
            if (temp != null)
                list = temp;
        }
        list.add(val);
    }