You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java虚拟线程(Virtual Threads)与ConcurrentHashMap的唤醒异常问题

Java虚拟线程与ConcurrentHashMap的死锁问题

在使用Java虚拟线程(VT)结合ConcurrentHashMap时,遇到了异常问题:当在computeIfAbsent方法内部获取锁时,虚拟线程可能永远无法被唤醒。该问题的出现与虚拟线程在载体线程上的调度方式相关,且可轻松复现此场景。

我知道ConcurrentHashMap内部使用synchronized关键字,而虚拟线程与synchronized的兼容性不佳,但官方并未提及需避免使用ConcurrentHashMap,这一点令人遗憾。

复现代码

class Scratch {
    public static void main(String[] args) throws InterruptedException {
        var lock = new ReentrantLock();
        var map = new ConcurrentHashMap<Integer, String>();

        var callables = new ArrayList<Callable<Void>>();
        for (int i = 0; i < 32 /* more than threads in FJ pool */; i++) {
            callables.add(() -> {
                System.out.println("Spawned thread " + Thread.currentThread().threadId());
                map.computeIfAbsent(1, k -> {
                    System.out.println("on lock() " + Thread.currentThread().threadId());
                    lock.lock();
                    try {
                        System.out.println("within lock() " + Thread.currentThread().threadId());
                    } finally {
                        lock.unlock();
                    }
                    return "";
                });
                System.out.println("Exiting " + Thread.currentThread().threadId());
                return null;
            });
        }

        new Thread(() -> {
            System.out.println("locking " + Thread.currentThread().threadId());
            lock.lock();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("unlocking " + Thread.currentThread().threadId());
            lock.unlock();
            System.out.println("unlocked " + Thread.currentThread().threadId());
        }).start();

        while (!lock.isLocked()) {
            Thread.sleep(10);
        }

        // it works with Executors.newCachedThreadPool()
        try (var es = Executors.newVirtualThreadPerTaskExecutor()) {
            es.invokeAll(callables);
        }
        System.out.println("done");
    }
}

内容的提问来源于stack exchange,提问作者milan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:01:17