Backend Development 7 min read

Avoiding Read‑Modify‑Write Race Conditions in ConcurrentHashMap Using Lambda compute

The article explains how read‑modify‑write race conditions can occur when updating a ConcurrentHashMap from multiple threads, demonstrates a failing JUnit example, and shows how using the atomic compute method with a lambda expression eliminates the race and ensures thread‑safe updates.

FunTester
FunTester
FunTester
Avoiding Read‑Modify‑Write Race Conditions in ConcurrentHashMap Using Lambda compute

java.util.concurrent provides two thread‑safe Map implementations, ConcurrentHashMap and ConcurrentSkipListMap , which are high‑performance but can still suffer from read‑modify‑write race conditions when used incorrectly.

In the “Wrong Demo” section a test updates a ConcurrentHashMap from three threads by reading a value, modifying it, and putting it back, which may cause the final count to be less than the expected number of updates, as shown by the JUnit assertion failure.

package com.fun;

import org.junit.Test;
import java.util.concurrent.ConcurrentHashMap;
import static org.junit.Assert.assertEquals;

public class TestFun {
    public void update(ConcurrentHashMap
map) {
        Integer result = map.get(1);
        if (result == null) {
            map.put(1, 1);
        } else {
            map.put(1, result + 1);
        }
    }

    @Test
    public void testUpdate() throws InterruptedException {
        final ConcurrentHashMap
map = new ConcurrentHashMap<>();
        Thread first = new Thread(() -> { update(map); update(map); update(map); update(map); update(map); });
        Thread second = new Thread(() -> { update(map); update(map); update(map); update(map); update(map); });
        Thread third = new Thread(() -> { update(map); update(map); update(map); update(map); update(map); });
        first.start();
        second.start();
        third.start();
        first.join();
        second.join();
        third.join();
        assertEquals(15, map.get(1).intValue());
    }
}

To eliminate the race, the article recommends using the atomic compute method with a lambda expression, which performs read, modify, and write in a single synchronized step.

public void update(ConcurrentHashMap
map) {
    map.compute(1, (key, value) -> {
        if (value == null) {
            return 1;
        }
        return value + 1;
    });
}

The source code of ConcurrentHashMap.compute is shown, illustrating how it acquires node‑level locks and updates the value atomically, ensuring thread safety.

Finally, the article notes that the lambda passed to compute runs under the map’s node lock, so no other thread may modify the same bucket concurrently.

JavaconcurrencylambdaThread SafetyConcurrentHashMapCompute
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.