JAVA集合面试分享八:ConcurrentHashMap实现原理详解

目录

首先我们先看下1.7版本的原理

1. HashEntrySegmentation

2. HashEntry

3. ReentrantLock

4. put 操作

5. get 操作

6. size 操作

再看下1.8版本的原理

数据结构的变化:

节点结构:

CAS操作:

synchronized关键字:

总结


首先我们先看下1.7版本的原理

ConcurrentHashMap 是 Java 中的一个线程安全的 HashMap 实现,用于在多线程环境中高效地进行并发操作。在 Java 1.7 中,ConcurrentHashMap 的实现进行了重大的改进,以提高并发性能。下面是 Java 1.7 中 ConcurrentHashMap 的实现原理的详细解释。

1. HashEntrySegmentation

在 Java 1.7 中,ConcurrentHashMap 采用了分段锁的策略,其核心思想是将一个大的 HashMap 分割成多个小的 HashMap,称为 Segment。每个 Segment 内部其实是一个小的 HashMap,它有自己的锁。当线程访问 ConcurrentHashMap 时,它首先需要根据 hashcode 找到对应的 Segment,然后在该 Segment 上进行同步操作,而不是在整个 ConcurrentHashMap 上进行同步。这样就可以实现真正的并发性,而不是像 Hashtable 或同步的 HashMap 那样的伪并发性。


2. HashEntry

在每个 Segment 中,存储数据的结构是 HashEntry,这与 HashMap 中的实现类似。HashEntry 是一个链表结构,用于处理哈希冲突。当两个元素的哈希值相同时,它们会被放在同一个 HashEntry 中。


3. ReentrantLock

每个 Segment 都有一个 ReentrantLock,用于在修改 HashEntry 时进行同步。这使得在多线程环境中,可以同时对不同的 Segment 进行操作,而不会相互干扰。这就是 ConcurrentHashMap 能够实现高并发性能的关键。


4. put 操作

当执行 put 操作时,首先计算 key 的 hashcode,找到对应的 Segment,然后在该 Segment 上加锁,最后将数据放入对应的 HashEntry 中。如果当前 HashEntry 中已经有数据,则需要遍历链表,找到合适的位置插入数据。


5. get 操作

get 操作不需要加锁,因为它只是读取数据,不会修改数据。这也是为了提高 ConcurrentHashMap 的读取性能。


6. size 操作

由于 ConcurrentHashMap 是并发的,因此在执行 size 操作时,需要遍历所有的 Segment,并将每个 Segment 中的元素数量相加。这个过程是需要加锁的,以防止在遍历过程中有其他线程修改数据。

总的来说,Java 1.7 中的 ConcurrentHashMap 通过分段锁的策略,实现了高并发性能。在每个 Segment 内部,其实就是一个小的 HashMap,这使得 ConcurrentHashMap 在多线程环境中的性能远远超过了 Hashtable 和同步的 HashMap

再看下1.8版本的原理

ConcurrentHashMap在1.8中的实现原理与1.7版本相比有了显著的变化。以下是ConcurrentHashMap 1.8实现原理的详解:

数据结构的变化

在1.8版本中,ConcurrentHashMap不再使用分段锁,而是使用了CAS(Compare-and-Swap)操作和synchronized关键字来实现并发控制。它也引入了红黑树(当链表长度大于一定阈值(默认为8)时,链表就转换为红黑树)作为数据结构,进一步提高搜索速度。

节点结构

1.8中的节点结构与1.7不同,它使用内部类Node作为最基本的存储单元,这个Node类继承了HashMap中的Entry。当两个节点的key-value相等时,新添加的节点会覆盖原有的节点,这与HashMap中的实现不同。

CAS操作

CAS操作是一种无锁化的技术,它包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置的值更新为新值B。否则,处理器不做任何操作。整个比较并交换的操作是一个原子操作。在ConcurrentHashMap中,CAS操作主要用于确保对Node节点的操作的线程安全性。

synchronized关键字

在1.8版本的ConcurrentHashMap中,synchronized关键字被用来修饰某些方法,以实现线程安全的操作。这是在1.8版本中引入的新特性,使得ConcurrentHashMap在保持高并发性能的同时,也能保证线程安全。

总的来说,ConcurrentHashMap 1.8版本通过引入红黑树、使用CAS操作和synchronized关键字,提高了并发性能和搜索速度,同时也保证了线程安全,这是相对1.7版本的主要改进。

总结

区别:

  • 1.7用的数组+链表,安全的方式为分段锁

  • 1.8用的数组+链表+红黑树,结构和HashMap一致,抛弃了分段锁,采用CAS+自旋以及Synchronized

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值