Java 线程安全的集合

一、早期线程安全的集合

1、Vector

Vector 与 ArrayList 类似,是长度可变的数组,与 ArrayList 不同的是,Vector 是线程安全的,它给几乎所有的 public 方法都加上了 synchronized 关键字。由于加锁导致性能降低,在不需要并发访问同一对象时,这种强制性的同步机制就显得多余,所以现在 Vector 已被弃用。

2、HashTable

HashTable 和 HashMap 类似,不同点是 HashTable 是线程安全的,但它给几乎所有 public 方法都加上了 synchronized 关键字,还有一个不同点是 HashTable 的K,V都不能是 null,但 HashMap 可以,所以它现在也因为性能原因被启用了。

二、Collections 包装方法

Vector 和 HashTable 被弃用后,他们被 ArrayList 和 HashMap 代替,但他们是线程不安全的,所以 Colletions 工具类中提供了相应的包装方法把他们包装成线程安全的集合。

List<E> synchronizedList = Collections.synchronizedList(new ArrayList<>());
Map<Object, Object> synchronizedMap = Collections.synchronizedMap(new HashMap<>(16));
Set<Object> synchronizedSet = Collections.synchronizedSet(new HashSet<>());
......

Collections 针对每种集合都声明了一个线程安全的包装类,在原集合的基础上添加了锁对象,集合中的每个方法都通过这个锁对象实现同步。

三、java.util.concurrent 包中的集合

1、ConcurrentHashMap

ConcurrentHashMap 和 HashTable 都是线程安全的集合,他们的不同主要是加锁粒度上的不同。HashTable 的加锁方法是给个方法都加上 synchronized 关键字,这样锁住的是整个 Table 对象。而ConcurrentHashMap 是更细粒度的加锁。

在 JDK 1.7 版本中,ConcurrentHashMap 是采用的分段锁,也就是 Segment 锁,每个 Segment 包含整个 Table 的一部分,这样不同分段之间的并发操作互不影响。

在 JDK 1.8 版本中,ConcurrentHashMap 采用的是 synchronized 和 CAS 对数组上的 Node 加锁,实现对某个链表进行加锁,进一步减少了并发冲突的概率。

2、CopyOnWriteArrayList 和 CopyOnWriteArraySet

它们是加了写锁的ArrayList和ArraySet,锁住的是整个对象,但读操作可以并发执行。

底层采用的 ReentrantLock 进行加锁实现并发控制的

3、其他并发集合

除此之外还有ConcurrentSkipListMap、ConcurrentSkipListSet、ConcurrentLinkedQueue、ConcurrentLinkedDeque等,至于为什么没有ConcurrentArrayList,原因是无法设计一个通用的而且可以规避ArrayList的并发瓶颈的线程安全的集合类,只能锁住整个list,这用Collections里的包装类就能办到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值