Backend Development 3 min read

Thread Safety Issues When Combining Thread‑Safe Methods: A ConcurrentHashMap Example

Even when using thread‑safe classes like Java's ConcurrentHashMap, combining multiple thread‑safe methods into a single operation can still cause race conditions, as demonstrated by a test where two threads concurrently execute get‑and‑put logic, leading to an unexpected map value and a failed assertion.

FunTester
FunTester
FunTester
Thread Safety Issues When Combining Thread‑Safe Methods: A ConcurrentHashMap Example

Beyond operation atomicity, another common source of thread‑unsafe behavior is the combination of safe methods; invoking several thread‑safe methods sequentially can still lead to race conditions.

ConcurrentHashMap is a high‑concurrency, high‑performance map implementation whose individual methods are thread‑safe. The following example demonstrates how combining its get and put calls in a single update method can produce incorrect results when executed by multiple threads.

public class TestTwoAtomicMethods {
  private final ConcurrentHashMap
map = new ConcurrentHashMap
();
  @Interleave
  public void update() {
      Integer result = map.get(1);
      if ( result == null ) {
        map.put(1, 1);
      } else {
        map.put(1, result + 1 );
      }
  }
  @Test
  public void testUpdate() throws InterruptedException {
    Thread first  = new Thread( () -> { update();   } );
    Thread second = new Thread( () -> { update();   } );
    first.start();
    second.start();
    first.join();
    second.join();
  }
  @After
  public void checkResult() {
    assertEquals( 2 , map.get(1).intValue() );
  }
}

The console output and the VMLens plugin visualization reveal that after the proxy line executes, both threads can still enter the if‑else block simultaneously. Each thread obtains the lock, reads a null value from the map, and then both execute map.put(1,1) , resulting in the final map value being 1 instead of the expected 2, causing the assertion to fail.

These screenshots illustrate the interleaving of get and put operations, where threads 13 and 14 acquire the object lock, read null, and then race to write, demonstrating that method‑level thread safety does not guarantee compound operation safety.

For further discussion, readers are invited to view the original article.

JavaConcurrencyThread SafetyConcurrentHashMapRace Condition
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.