这是一个组合并发列表多重映射实现。较低级别的实现会更好,但也更复杂。
忽略子列表中的 O(n) 删除,这是将 ConcurrentMap 和 CopyOnWriteArrayList 组合成功能性 ConcurrentMultimap 的正确方法吗?是否有任何 Unresolved 数据竞争?
private final ConcurrentMap<K, Collection<V>> map = ...; // inconsequential
public boolean put(K key, V value) {
Collection<V> list = map.get(key);
if(list != null) {
list.add(value);
return true;
}
// put if absent double check to avoid extra list creation
list = new CopyOnWriteArrayList<V>();
list.add(value);
Collection<V> old = map.putIfAbsent(key,value);
if(old != null) old.add(value);
return true;
}
public boolean remove(Object key, Object value) {
Collection<V> list = map.get(key);
if(list == null) return false;
// O(n) remove is the least of my worries
if( ! list.remove(value)) return false;
if( ! list.isEmpty()) return true;
// double-check remove
if( ! map.remove(key,list)) return true; // already removed! (yikes)
if(list.isEmpty()) return true;
// another entry was added!
Collection<V> old = map.putIfAbsent(key,list);
if(old == null) return true;
// new list added!
old.addAll(list);
return true;
}
最佳答案
我认为你有一场比赛。我看到的问题是“put”中的线程无法确保插入的列表未被删除和/或替换为另一个列表。
观察:
线程 1 调用 put(),并检索(或创建)与该键关联的列表。同时,线程 2 从映射中删除该列表。数据丢失。
我认为您需要添加一个重试循环来验证添加到 map 后正确的列表是否位于 map 中。
关于java - 并发多重映射放置和删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/985012/