java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java集合与映射

Java常用集合与映射的线程安全问题小结

作者:jiajia651304

本文给大家介绍Java常用集合与映射的线程安全问题小结,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

Java常用集合与映射的线程安全问题深度解析

一、线程安全基础认知

在并发编程环境下,当多个线程同时操作同一集合对象时,若未采取同步措施,可能导致以下典型问题:

二、典型非线程安全集合问题分析

1. ArrayList的并发陷阱

// 错误示例
List<Integer> list = new ArrayList<>();
ExecutorService pool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
    pool.execute(() -> list.add(new Random().nextInt()));
}
// 运行结果可能包含:元素丢失、size值异常、数组越界异常等

问题根源

2. HashMap的并发灾难

Map<String, Integer> map = new HashMap<>();
// 并发执行put操作可能导致:
// 1. JDK7及之前版本:环形链表导致CPU 100%
// 2. JDK8+版本:数据丢失或size计数错误
// 3. 迭代时ConcurrentModificationException

底层机制

3. HashSet的隐藏风险

Set<Integer> set = new HashSet<>();
// 本质是HashMap的包装类,所有线程安全问题与HashMap一致
// add()方法并发调用时可能产生元素丢失

三、线程安全解决方案对比

1. 同步包装方案

// 使用Collections工具类
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Object> syncMap = Collections.synchronizedMap(new HashMap<>());
// 特征:
// 1. 所有方法使用synchronized同步块
// 2. 迭代器需要手动同步
// 3. 锁粒度大,性能较差

2. 传统线程安全集合

// Vector/Hashtable方案
Vector<String> vector = new Vector<>(); 
Hashtable<String, Integer> table = new Hashtable<>();
// 缺点:
// 1. 全表锁导致吞吐量低
// 2. 已逐渐被并发容器取代

3. 现代并发容器(java.util.concurrent包)

3.1 CopyOnWriteArrayList

List<String> cowList = new CopyOnWriteArrayList<>();
// 实现原理:
// 1. 写操作时复制新数组
// 2. 最终一致性保证
// 适用场景:读多写少(如白名单配置)

3.2 ConcurrentHashMap

Map<String, Object> concurrentMap = new ConcurrentHashMap<>();
// JDK8+实现特点:
// 1. 分段锁升级为CAS+synchronized
// 2. 节点锁粒度(锁单个哈希桶)
// 3. 支持并发度设置

3.3 ConcurrentSkipListMap

NavigableMap<String, Integer> skipMap = new ConcurrentSkipListMap<>();
// 特征:
// 1. 基于跳表实现的有序Map
// 2. 无锁读取,写入使用CAS

四、并发容器实现原理剖析

1. CopyOnWriteArrayList写时复制机制

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

2. ConcurrentHashMap并发控制

JDK8关键实现

3. 并发队列实现对比

队列类型锁机制适用场景
ConcurrentLinkedQueueCAS无锁高并发生产者消费者模式
LinkedBlockingQueueReentrantLock双锁有界阻塞队列
ArrayBlockingQueue单ReentrantLock固定容量队列

五、最佳实践与注意事项

1. 选型决策指南

2. 常见误区规避

// 错误示例:即使使用ConcurrentHashMap仍需同步
if (!map.containsKey(key)) {
    map.put(key, value); // 非原子操作
}
// 正确写法:
map.putIfAbsent(key, value);

3. 性能优化建议

六、高级话题扩展

1. 弱一致性迭代器

2. 原子复合操作

// 使用merge方法实现原子计数
ConcurrentHashMap<String, Long> counterMap = new ConcurrentHashMap<>();
counterMap.merge("key", 1L, Long::sum);

3. 分段锁的演进

总结与建议

开发者应当建立以下意识:

通过合理选择并发容器并遵循最佳实践,可以显著降低多线程环境下的集合操作风险,构建高性能高可靠的Java应用系统。

到此这篇关于Java常用集合与映射的线程安全的文章就介绍到这了,更多相关java集合与映射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文