\$\begingroup\$
\$\endgroup\$
12
I've implemented a concurrent multimap that support concurrent put and remove but I'm unsure of its correctness. I would appreciate your feedback.
public class ConcurrentMultiMap<K, V> {
private static ConcurrentHashMap emptySet = new ConcurrentHashMap();
private ConcurrentHashMap<K, ConcurrentHashMap<V, Object>> map = new ConcurrentHashMap<>();
// return true if the method increased the size of the multimap or false if the multimap already contained the key-value pair
public boolean put(K k, V v) {
Preconditions.checkNotNull(k);
Preconditions.checkNotNull(v);
boolean tryAgain;
boolean success = true;
do {
ConcurrentHashMap<V, Object> oldSet = map.get(k);
if (oldSet == null) {
tryAgain = map.putIfAbsent(k, new ConcurrentHashMap<>(Collections.singeltonMap(v, 1))) != null;
} else {
success = oldSet.putIfAbsent(v, 1) == null; //I do not allow multiple equal values for the same key
if (success) {
// if the put was a success we check that the key was not removed from the map by a concurrent remove operation.
ConcurrentHashMap<V, Object> currentSet = map.get(k);
tryAgain = currentSet == null || !currentSet.contains(v);
} else {
return false;
}
} while(tryAgain);
return success;
}
// returns true if the multimap changed
public boolean remove(K k, V v) {
Preconditions.checkNotNull(k);
Preconditions.checkNotNull(v);
ConcurrentHashMap<V, Object> oldSet = map.get(k);
if (oldSet == null) {
return false;
}
if (oldSet.remove(v) != null) {
if (oldSet.size() == 0) {
map.remove(k, emptySet);
}
return true;
}
return false;
}
}
-
\$\begingroup\$ You're not extending from any other collection classes/interfaces; do you provide functionality for getting things from the multimap? \$\endgroup\$BenC– BenC2017年08月23日 00:40:20 +00:00Commented Aug 23, 2017 at 0:40
-
\$\begingroup\$ I'm implementing guava multimap. I didn't include the full implementation of the class in the code above to keep the focus on the put/remove methods. \$\endgroup\$Eth0– Eth02017年08月23日 05:56:31 +00:00Commented Aug 23, 2017 at 5:56
-
\$\begingroup\$ What do you mean by "concurrent"? \$\endgroup\$Solomon Ucko– Solomon Ucko2017年08月24日 14:30:17 +00:00Commented Aug 24, 2017 at 14:30
-
\$\begingroup\$ @SolomonUcko concurrent means that the methods will be called from multiple threads of execution. In the implementation above I'm using concurrent hash map, which is a class from the java.util package which guarantees a form of consistency when used from several threads, moreover it does so without locking the entire map and thus it is considered efficient. You can read more about it here docs.oracle.com/javase/tutorial/essential/concurrency and here docs.oracle.com/javase/8/docs/api/java/util/concurrent/… \$\endgroup\$Eth0– Eth02017年08月26日 15:45:01 +00:00Commented Aug 26, 2017 at 15:45
-
\$\begingroup\$ That's what I thought, but can you take a look at my answer and explain why it's wrong if it's wrong? \$\endgroup\$Solomon Ucko– Solomon Ucko2017年08月26日 21:06:43 +00:00Commented Aug 26, 2017 at 21:06
1 Answer 1
\$\begingroup\$
\$\endgroup\$
5
You should have HashMap<K, Set<V>>
, not ConcurrentHashMap<K, ConcurrentHashMap<V, Object>>
.
answered Aug 23, 2017 at 16:25
-
\$\begingroup\$ Why did someone down vote? Is the answer too short? Is it incorrect? If it is incorrect, please explain why. \$\endgroup\$Solomon Ucko– Solomon Ucko2017年08月23日 23:37:30 +00:00Commented Aug 23, 2017 at 23:37
-
2\$\begingroup\$ I think it's because you didn't explain, why he should use HashMap. And you ask what he means by 'concurrent', which is imo necessary to understand beforehand, to be able to give a proper answer. \$\endgroup\$slowy– slowy2017年08月24日 10:47:00 +00:00Commented Aug 24, 2017 at 10:47
-
\$\begingroup\$ @slowy, I added a comment to the question, I'll edit later. \$\endgroup\$Solomon Ucko– Solomon Ucko2017年08月24日 14:30:54 +00:00Commented Aug 24, 2017 at 14:30
-
1\$\begingroup\$ My implementation relies heavily on the concurrency guarantees given by ConcurrentHashMap. By replacing it with HashMap not only that my code will not support concurrent put and remove it will not even support modifications from different threads done in a sequential manner due to lack of memory barriers. \$\endgroup\$Eth0– Eth02017年08月28日 08:52:25 +00:00Commented Aug 28, 2017 at 8:52
-
\$\begingroup\$ @EladTolochinsky Oh, oops. It looked like you were defining
ConcurrentHashMap
, notConcurrentMultiMap
. Should I delete this answer? \$\endgroup\$Solomon Ucko– Solomon Ucko2017年08月28日 12:13:11 +00:00Commented Aug 28, 2017 at 12:13
Explore related questions
See similar questions with these tags.
lang-java