HashMap 在多线程 Java 应用程序中行为异常
·
场景: 线程 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());
}

这个都能读出来
更多推荐


所有评论(0)