HashMap为什么是线程不安全的
import java.util.HashMap;
/**
* 由于 HashMap 的线程不安全性,最终的 HashMap 值可能不符合预期。
* 例如,预期值应该是 0(因为增加和减少操作相互抵消),但实际上可能得到一个不同的值。
*/
public class HashMapThreadUnsafeDemo {
public static void main(String[] args) throws InterruptedException {
// 创建一个 HashMap
HashMap<String, Integer> map = new HashMap<>();
// 初始化 HashMap
map.put("key", 0);
// 创建并启动线程
Thread incrementThread = new Thread(new IncrementTask(map));
Thread decrementThread = new Thread(new DecrementTask(map));
incrementThread.start();
decrementThread.start();
// 等待所有线程完成
incrementThread.join();
decrementThread.join();
// 输出最终的 HashMap
System.out.println("最终的 HashMap: " + map);
}
static class IncrementTask implements Runnable {
private final HashMap<String, Integer> map;
public IncrementTask(HashMap<String, Integer> map) {
this.map = map;
}
@Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
int value = map.get("key");
value++;
map.put("key", value);
System.out.println("IncrementThread: key=" + value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
static class DecrementTask implements Runnable {
private final HashMap<String, Integer> map;
public DecrementTask(HashMap<String, Integer> map) {
this.map = map;
}
@Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
int value = map.get("key");
value--;
map.put("key", value);
System.out.println("DecrementThread: key=" + value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
同时put碰撞导致数据丢失
两个同样put的key发生了碰撞,根据hash值计算出来的bucket位置一样,两个线程又同时判断该位置是空的,可以写入两个不同的value便会添加到数组的同一个位置,最终就只会保留一个数据,丢失一个数据
可见性问题无法保证
死循环造成CPU100%
推荐使用线程安全同时性能比较好的ConcurrentHashMap