线程安全的集合和hashMap

线程安全的集合

Vector
相比较ArrayList,使用了synchronized关键字,线程安全,但是效率低下,不怎么使用
hashTable
相比较hashMap,使用了synchronized关键字,线程安全,但是也不常见
ConcurrentHashMap
相当于hashMap的高并发并线程安全的版本

认识hashMap

1.hashMap的组成

hashMap在jdk1.8之前,底层数据结构由数组和链表组成,在jdk1.8及之后,插入了红黑树,也就是 数组+链表+红黑树。在链表长度达到8时,数组长度达到64,链表会转化为红黑树,链表长度为6时,又会变回链表,而在链表达到8时,数组长度小于64,则可能会优先进行数组扩容。hashMap的负载因子是0.75,扩容为2倍。

jdk1.8之前jdk1.8及之后
数组+链表数组+链表+红黑树
头插法尾插法
负载因子是0.75,扩容为2倍

注:头插法可能会导致,cpu占有率达到100%。如下图,比如在并发扩容情况下,可能会导致扩容时A指向B的同时B指向A,形成死循环。

2. hashMap的put原理

hashMap的put()方法包含了添加和修改这两个功能,这是因为调用put()方法时,首先要根据设定的key值来计算hash值,目的在于计算数组的下标(jdk1.8及之后,hashMap底层数据结构 = 数组 + 链表 + 红黑树),这里会有一个叫哈希冲突的,计算的hash值没有一致,表明没有产生哈希冲突,则表示该数组为空,此时,表示调用的put()方法为添加数据;若哈希冲突了,表示这个key已经存在,就对应位置,将对应的value覆盖,此时,表示调用的put()方法为修改数据。
 

 认识ConcurrentHashMap

1.为什么有ConcurrentHashMap?

通常情况下,我们都会使用hashMap,但它毕竟是线程不安全的,在保证线程安全的情况下,hashTable也可以使用,二则恰好相反,hashTable效率太低了,而ConcurrentHashMap恰好保证了这两个优点。ConcurrentHashMap在 jdk1.7 中,它是通过分段锁的方式来实现线程安全的。意思是将哈希表分成许多片段 Segment,而 Segment 本质是一个可重入的互斥锁,所以叫做分段锁;而在 jdk1.8它是 数组+链表+红黑树,采用了 CAS 操作和 synchronized 【保证了并发更新的安全】(synchronized 则是JVM直接支持的,JVM 能够在运行时作出相应的优化措施:锁粗化、锁消除、锁自旋等)来实现的。

2.CAS算法

CAS算法实现无锁化的修改值的操作,他可以大大降低锁代理的性能消耗【可以联想一下乐观锁】。就是不断地去比较当前内存中的变量值与你指定的一个变量值是否相等,如果相等,则接受你指定的修改的值,反之不接受。因为当前线程中的值已经不是最新的值,你的修改很可能会覆盖掉其他线程修改的结果

3.怎么保证线程安全

ConcurrentHashMap只有put()方法中使用了synchronized,在加锁时是使用头结点作为同步锁对象。

4.使用了CAS算法为什么还要synchronized

资源竞争小时,CAS算法是非常适用的,不用进行内核态和用户态之间的线程上下文切换,同时自旋概率也会大大减少,提升性能;当大量线程对同一资源进行写和读操作,自旋概率会大大增加,从而浪费CPU资源,降低性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值