返回
Java 面经之思考:巧用 ConcurrentHashMap 应对多线程安全
见解分享
2023-10-25 15:57:21
HashMap 线程不安全成因探究
HashMap 是一种基于哈希表的集合,在并发场景下,多个线程可能同时对 HashMap 进行读写操作。此时,就有可能出现线程安全问题。
HashMap 的线程不安全主要源于其底层的数据结构:链表 。当多个线程同时对同一个链表进行修改时,可能会出现链表成环的情况。如果在 get 操作时恰好遇到链表成环,就会形成死循环,导致程序崩溃。
应对策略:巧用 ConcurrentHashMap
为了解决 HashMap 的线程不安全问题,Java 提供了 ConcurrentHashMap 类。ConcurrentHashMap 采用了分段锁机制,将 HashMap 分成多个小的 segment,每个 segment 都有自己的锁。当多个线程同时访问 HashMap 时,它们只需要获取对应 segment 的锁即可,互不干扰,从而保证了线程安全性。
ConcurrentHashMap 的使用非常简单,只需要在创建 HashMap 时指定并发级别即可。并发级别决定了 HashMap 被划分为多少个 segment,并发级别越大,并发性能越好,但内存消耗也越大。一般情况下,将并发级别设置为 CPU 核数的 2 倍即可。
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(16);
其他应对策略
除了使用 ConcurrentHashMap 外,还可以通过其他方式应对 HashMap 的线程不安全问题:
- **使用 synchronized ** :在对 HashMap 进行读写操作时,使用 synchronized 关键字对代码块进行同步,确保同一时刻只有一个线程可以访问 HashMap。
synchronized (map) {
// 对 map 进行读写操作
}
- 使用 Collections.synchronizedMap() 方法 :将 HashMap 包装成一个线程安全的 Map,Collections.synchronizedMap() 方法会返回一个线程安全的 Map 视图,对该视图进行操作等同于对原 HashMap 进行操作。
Map<String, Integer> map = Collections.synchronizedMap(new HashMap<>());
总结
HashMap 的线程不安全性是 Java 面试中常见的考察点。掌握应对策略,特别是使用 ConcurrentHashMap,是解决此问题的关键。通过分段锁机制,ConcurrentHashMap 巧妙地解决了 HashMap 的线程安全问题,为多线程编程提供了强大的支持。