Параллельная мультикарта положить и удалить - PullRequest
2 голосов
/ 12 июня 2009

Это составленный параллельный список реализации нескольких карт. Реализация более низкого уровня была бы лучше, но более сложной.

Игнорирование удаления O (n) в подсписке, является ли это правильным способом объединения ConcurrentMap и CopyOnWriteArrayList в функциональный ConcurrentMultimap? Есть ли нерешенные гонки данных?

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

1 Ответ

3 голосов
/ 12 июня 2009

Я думаю, что у вас есть гонка. Проблема, которую я вижу, заключается в том, что поток, находящийся в состоянии 'put', НЕ МОЖЕТ быть уверен, что вставляемый список не был удален и / или заменен другим списком.

Обратите внимание:

Поток 1 вызывает метод put () и получает (или создает) список, связанный с ключом. Тем временем Поток 2 удаляет этот список с карты. Данные потеряны.

Я думаю, вам нужно добавить цикл повторных попыток, чтобы убедиться, что правильный список находится на карте после добавления к нему.

...