当前位置: 代码迷 >> 综合 >> 【集合】HashTable ConcurrentHashMap
  详细解决方案

【集合】HashTable ConcurrentHashMap

热度:87   发布时间:2023-12-11 15:27:11.0

学习资料来源: link.

HashMap在多线程环境下存在线程安全问题,怎么解决?
  • 使用Collections.synchronizedMap(Map)创建线程安全的map集合;
  • Hashtable
  • ConcurrentHashMap
Collections.synchronizedMap是怎么实现线程安全的?

在SynchronizedMap内部维护了一个普通对象Map,还有排斥锁mutex
在这里插入图片描述
我们在调用这个方法的时候就需要传入一个Map,可以看到有两个构造器,如果你传入了mutex参数,则将对象排斥锁赋值为传入的对象。

如果没有,则将对象排斥锁赋值为this,即调用synchronizedMap的对象,就是上面的Map。

创建出synchronizedMap之后,再操作map的时候,就会对方法上锁
在这里插入图片描述

Hashtable的特点
  • 对数据操作的时候都会上锁,所以效率比较低下。
  • Hashtable 是不允许键或值为 null 的,HashMap 的键值则都可以为 null。
  • 初始化容量不同:HashMap 的初始容量为:16,Hashtable 初始容量为:11,两者的负载因子默认都是:0.75。
  • 扩容机制不同:当现有容量大于总容量 * 负载因子时,HashMap 扩容规则为当前容量翻倍,Hashtable 扩容规则为当前容量翻倍 + 1。
ConcurrentHashMap JDK1.7

在这里插入图片描述

  • 由 Segment 数组、HashEntry 组成,和 HashMap 一样,仍然是数组加链表。
  • HashEntry跟HashMap差不多的,但是不同点是,他使用volatile去修饰了他的数据Value还有下一个节点next。
  • 原理上来说,ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。
  • 并发度==segment的数量,就是说如果容量大小是16他的并发度就是16,可以同时允许16个线程操作16个Segment而且还是线程安全的。
put方法:
  • 拿到锁
  • 定位Segment
  • 通过 key 的 hashcode 定位到 HashEntry
  • 遍历该 HashEntry,如果不为空则判断传入的 key 和当前遍历的 key 是否相等,相等则覆盖旧的 value。
  • 不为空则需要新建一个 HashEntry 并加入到 Segment 中,同时会先判断是否需要扩容。
  • 释放锁
get方法:
  • 只需要将 Key 通过 Hash 之后定位到具体的 Segment ,再通过一次 Hash 定位到具体的元素上。
  • 由于 HashEntry 中的 value 属性是用 volatile 关键词修饰的,保证了内存可见性,所以每次获取时都是最新值。
  • ConcurrentHashMap 的 get 方法是非常高效的,因为整个过程都不需要加锁。
ConcurrentHashMap JDK1.8

在这里插入图片描述

  • 抛弃了原有的 Segment 分段锁,而采用了 synchronized +CAS 来保证并发安全性。
  • 跟HashMap很像,也把之前的HashEntry改成了Node,但是作用不变,把值和next采用了volatile去修饰,保证了可见性,并且也引入了红黑树,在链表大于一定值的时候会转换(默认是8)。
put方法:
  • 根据 key 计算出 hashcode 。
  • 判断是否需要进行初始化。
  • 当前 key 定位出的 Node,如果为空表示当前位置可以写入数据,利用 CAS 尝试写入,失败则自旋保证成功。
  • 如果当前位置的 hashcode == MOVED == -1,则需要进行扩容。
  • 如果都不满足,则利用 synchronized 锁写入数据。
  • 如果数量大于 TREEIFY_THRESHOLD 则要转换为红黑树。
get方法:
  • 根据计算出来的 hashcode 寻址,如果就在桶上那么直接返回值。
  • 如果是红黑树那就按照树的方式获取值。
  • 就不满足那就按照链表的方式遍历获取值。

————————————————
版权声明:本文为CSDN博主「敖 丙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35190492/article/details/103589011

  相关解决方案