Backend Development 3 min read

Recursive Update Bug in ConcurrentHashMap.computeIfAbsent Causing Infinite Loop and CPU Spike

The article explains a bug in Java's ConcurrentHashMap.computeIfAbsent that can cause recursive updates and infinite loops, leading to CPU spikes, and shows that newer Java versions throw an IllegalStateException while recommending avoiding nested computeIfAbsent/putIfAbsent calls, with a code example.

Cognitive Technology Team
Cognitive Technology Team
Cognitive Technology Team
Recursive Update Bug in ConcurrentHashMap.computeIfAbsent Causing Infinite Loop and CPU Spike

When two keys produce a hash collision, nesting ConcurrentHashMap.computeIfAbsent inside another computeIfAbsent or putIfAbsent can trigger a bug in ConcurrentHashMap#computeIfAbsent . The bug makes the current thread enter an infinite loop, causing the CPU usage to sky‑rocket. In newer Java versions the operation throws an IllegalStateException("Recursive update") instead of looping forever.

The simple solution is to avoid nesting computeIfAbsent (or putIfAbsent ) calls inside another computeIfAbsent on the same ConcurrentHashMap .

Example code demonstrating the issue:

package com.renzhikeji.demo;

import java.util.concurrent.*;

/**
 * @author 认知科技技术团队
 * 微信公众号:认知科技技术团队
 */
public class JdkDemo {
    public static void main(String[] args) throws Exception {
        ConcurrentHashMap map = new ConcurrentHashMap(9);
        Num n1 = new Num(3);
        Num n2 = new Num(19);
        System.out.println(n1.hashCode());
        System.out.println(n2.hashCode());

        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                map.computeIfAbsent(n1, k -> 200);
            }).start();
        }
        map.computeIfAbsent(n1, k1 -> map.computeIfAbsent(n2, k2 -> 200));
    }

    static class Num {
        private int i;
        public Num(int i) { this.i = i; }
        @Override
        public int hashCode() { return i; }
    }
}

Running the above code on older Java versions leads to a dead loop and high CPU usage. On newer Java releases the runtime throws:

java.lang.IllegalStateException: Recursive update

For further reading, see the following resources:

Seata DSProxy deadlock analysis

Stack Overflow discussion on ConcurrentHashMap deadlock

Apache Dubbo pull request addressing the issue

backendJavamultithreadingbugConcurrentHashMapcomputeIfAbsent
Cognitive Technology Team
Written by

Cognitive Technology Team

Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.

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.