场景: 线程 A 和线程 B 同时向同一个桶插入数据。
线程 A 计算出位置,准备插入节点 NodeA。
线程 B 也计算出相同位置,准备插入节点 NodeB。
如果线程 B 在线程 A 更新桶的引用之前完成了写入,线程 A 随后的写入可能会覆盖线程 B 的更新,或者导致链表指针指向错误的节点。
结果: 某些数据永远无法被读取到(看似“缺失”),或者读取到了处于中间状态的错误数据
方案:
ConcurrentHashMap 的内部实现专门针对并发扩容进行了设计,确保在多线程扩容时不会出现链表成环的情况

    // 使用 ConcurrentHashMap 替代 HashMap
    // 它是线程安全的,且在高并发下性能远优于 synchronizedMap
    private static final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        Runnable writer = () -> {
            for (int i = 0; i < 1000; i++) {
                map.put("key" + i, i);
            }
            System.out.println("Writer finished.");
        };

        Runnable reader = () -> {
            for (int i = 0; i < 1000; i++) {
                // get 操作是无锁的,不会阻塞,也不会导致死循环
                Integer value = map.get("key" + i);
                if (value != null) {
                    // 在实际生产中,避免在循环中频繁打印,这里仅做演示
                     System.out.println(value);
                }
            }
            System.out.println("Reader finished.");
        };

        Thread t1 = new Thread(writer);
        Thread t2 = new Thread(reader);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Total entries: " + map.size());
    }

在这里插入图片描述
这个都能读出来

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐