集合的线程安全性、为什么HashMap,ArrayList不是线程安全的?体现在哪?

一.集合的线程安全性

      我们通常所讲的某个集合是线程安全的,指的是单个操作是线程安全的,也就是需要具体到某个变量或方法的,如果是多个连续的操作,并不能保证这些连续的操作是线程安全的.

      比如我们通常说hashTable是线程安全的.那假如现在有一个hashTable,里面有一个键值对key:test
现在有两个线程a和b均需要给这个key的值末尾添加字符a,预期的结果是这样的key:testaa
那假设这两个线程的执行顺序是这样的:
   1.线程a读出key的值:test
   2.线程b读出key的值:test
   3.线程a在末尾添加字符a,然后进行写入
   4.线程b在末尾添加字符a,然后进行写入
此时的结果是key:testa,并不是我们预期的结果,那hashtable算不算线程安全的呢?

      还是算的,因为线程安全是指 变量或方法在多线程环境下能够被安全有效的访问,针对于hashTable的单个方法来说,确实是进行了正确的处理,所以是线程安全的.

二.线程不安全集合举例分析.

1.ArrayList.

      比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。

      在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
      而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
      那好,我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了.

2.HashMap.

以jdk1.8为例分析.
      在jdk1.8中,hashMap将头插法改成了尾插法,解决了死循环的问题,但是还会有数据丢失的问题,这个场景很多博客都说的不对,这里着重说明一下.

      假设有两个线程a和b,同时往hashMap中put键值对,这两个键值对的key不相等,但是hash值是一样的.

      那在hashMap中,因为没有加锁,是并行执行的,所以当两个线程都同时执行到以下代码时,tab[i]最终只会指向其中一个,另一个数据会被覆盖,map中只会有一条数据,也就造成数据丢失的情况.
在这里插入图片描述

三.concurrentHashMap相对于hashMap的优化(jdk1.8)

      而在concurrentHashMap中,采用了CAS+synchronized的方式(jdk1.8)去处理多线程,就是一个Node数组+链表/红黑树的结构,锁的是Node数组中的某个Node节点.
在这里插入图片描述

当某个Hash值对应Node数组中的位置为空时,采用CAS进行赋值.
在这里插入图片描述
当某个Hash值对应的数组位置不为空时,会锁住该数组中Node节点,并以该Node节点为链表的首节点,依次向后添加新节点.
在这里插入图片描述
      所以,当出现上面那种情况时---->有两个线程a和b,同时往concurrentHashMap中put键值对,并且这两个键值对的key不相等,但是hash值是一样的.

      两个线程会先同时进行CAS操作,给Node数组中对应的位置赋值,此时一定一个执行成功,往Node数组中成功添加a节点,另一个执行失败,那么执行失败的这个线程会使用synchronized锁住a节点,将这个a节点作为链表的首节点,然后在后面添加新节点,此时map中两个键值对都可以添加成功,就是线程安全的了.

======================================================================================================
如果你需要阅读专业书籍来提升自己,可以关注博主的公众号,回复 图书即可获得几百本程序员必读书籍.

包含以下所有分类中的各种经典书籍.
在这里插入图片描述
006QslZHly8h66jmes3esj30go0gowg9.jpg

今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员bling

义父,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值