Camilla
Camilla

Reputation: 170

I want to have both computeIfPresent and putIfAbsent into one atomic function

workObjectMap.computeIfPresent(key, (k,v) -> {
    v.memberIdSet.addAll(memberIdSet);
    v.memberPositionSet.addAll(memberPositionSet);
    return v;
});
// If it.remove() in run() is called at this point,
// there is a risk of the same work being done twice
workObjectMap.putIfAbsent(key, new WorkObjectValue(memberIdSet, memberPositionSet));

I have the above code. In a separate thread I may be removing from the workObjectMap. I want an atomic function that modifies the value if the key is present, and if its not, it puts the key/value.

In my current code, there is a chance that the remove will happen in between the computeIfPresent and putIfAbsent so that the same item that was already added to the map, would be added again.

How do I block any removes in between these 2 method calls? (computeIfPresent and putIfAbsent)

Upvotes: 6

Views: 1275

Answers (1)

Didier L
Didier L

Reputation: 20579

Use Map.compute():

workObjectMap.compute(key, (k,v) -> {
    if (v == null) return new WorkObjectValue(memberIdSet, memberPositionSet);
    v.memberIdSet.addAll(memberIdSet);
    v.memberPositionSet.addAll(memberPositionSet);
    return v;
});

Note that the ConcurrentHashMap Javadoc explicitly states that this is atomic.

Upvotes: 7

Related Questions