java的各种集合为什么不安全(List、Set、Map)以及代替方案 (3)

而保证 set 的不重复性质的关键,显然就在于 CopyOnWriteArrayList 的 addIfAbsent 方法,我们还是点进 CopyOnWriteArrayList 源码看一看这个方法的实现:

java的各种集合为什么不安全(List、Set、Map)以及代替方案

其中的 indexOfRange 方法:

java的各种集合为什么不安全(List、Set、Map)以及代替方案

可以看到,也是加了 Monitor 锁来进行的,整个过程是这样的:

获取本来的 set ,是一个数组,以快照形式返回当前的数组;

indexOfRange 方法通过遍历查找查找元素出现位置,addIfAbsent方法完成不存在则加入,如果前一个为 false 后一个就不会执行;

加锁

current 再次获取一次当前的快照,因为有可能第一次判断的过程有了其他线程的插入或者修改操作,此时已经不像等,就进入分支进行判断是否存在;

否则就要加入这个元素,和 CopyOnWriteArrayList 添加元素的最后操作是一样的;

解锁

总结一下就是,线程安全的 Set 集合完全利用了 CopyOnWriteArrayList 集合的方法,对应的操作也是读写分别处理,写时复制的策略,通过 jvm 层面的锁来保证安全,那么保证不重复的方法就是遍历进行比较。

这样看来,相比于基于 HashMap 的去重方法,效率肯定会降低,不过如果基于线程安全的 HashMap ,插入操作从hash、比较、到考虑扩容各方面会因为加锁的过程更复杂,而对于一个不重复的 Set 来说,完全没必要,所以应该综合考虑之下采用了 List 为基础,暴力循环去重。


三、HashMap 的线程不安全

关于 HashMap 的相关问题,源码里已经分析过,大体是这样的。

不安全:

普通读写不一致问题;

死循环问题;

ConcurrentModificationException 异常。

解决:

util包的Hashtable集合线程安全;

用 synchronizedMap(new HashMap())包装;

使用 juc 包的 ConcurrentHashMap。

HashMap 和 ConcurrentHashMap 的源码分析:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpddjx.html