万万哇 发表于 2024-8-23 01:45:22

线程安全的集合和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倍 https://i-blog.csdnimg.cn/direct/e12b88b50b60410f8117e678dee3b473.png
注:头插法可能会导致,cpu占有率达到100%。如下图,比如在并发扩容情况下,可能会导致扩容时A指向B的同时B指向A,形成死循环。
https://i-blog.csdnimg.cn/direct/d6535e21ac5a4a8886a91ddf3b734984.png
2. hashMap的put原理

hashMap的put()方法包含了添加和修改这两个功能,这是因为调用put()方法时,起首要根据设定的key值来计算hash值,目的在于计算数组的下标(jdk1.8及之后,hashMap底层数据布局 = 数组 + 链表 + 红黑树),这里会有一个叫哈希辩说的,计算的hash值没有同等,表明没有产生哈希辩说,则表示该数组为空,此时,表示调用的put()方法为添加数据;若哈希辩说了,表示这个key已经存在,就对应位置,将对应的value覆盖,此时,表示调用的put()方法为修改数据。
 
https://i-blog.csdnimg.cn/direct/892e2ceafac4452b98fb199dc24a67e6.png
 认识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资源,降低性能

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 线程安全的集合和hashMap