Reputation: 45702
I have: Map<K1, Map<K2, V>>
, where:
I want: Make map concurrent. I want concurrently:
UPDATED question: Is code below error prone?
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!
}
Upvotes: 0
Views: 162
Reputation: 269797
This code is subject to a race condition.
Multiple threads can detect that map.get(v.k1) == null
. Depending on the order of execution, one of these threads can assign a new submap for k1
and clobber a submap to which other threads have already added their values.
One of the more prominent features of ConcurrentMap
is its putIfAbsent()
method.
map.putIfAbsent(v.k1, new ConcurrentHashMap<>());
map.get(v.k1).put(v.k2, v);
Upvotes: 1