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<Integer,Integer> map = new ConcurrentHashMap<Integer,Integer>();
  @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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaconcurrencythread safetyConcurrentHashMaprace condition
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

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.