JAVA并发容器源码分析【二】ConcurrentHashMap分析之数据结构(JDK7与JDK8)

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

文章首发于:clawhub.club


ConcurrentHashMap的数据结构奠定了其高并发编程中的作用。其基本的数据结构还是离不开其本源HashMap。比如JDK8中他们同样用了数组+链表+红黑树,只不过在ConcurrentHashMap中增加了一些无锁技术,来实现多线程操作容器。

JDK7

先贴两张盗的图(实在不想画图,就找了两张喜欢的)

201910301005\_1.png

1.7-1.png

201910301005\_2.png

1.7-2.png

从图中可以看出,其数据结构主要由Segment数组+HashEntry数组+链表组成,也就是说定位一个数据时,要通过两次Hash计算。

JDK7的ConcurrentHashMap主要通过锁分段技术实现对资源的并发访问。Segment数组中的每个Segment,都是继承自ReentrantLock (可重入锁,后期再写一个锁的专题),即其锁的粒度为Segment。

在一个线成获取到这个Segment的锁的时候,其他线成可以访问别的Segment,以此增加了容器处理的吞吐量。

JDK8

JDK8的HashMap中比JDK7多了一个红黑树以用来增加数据分布的平衡性。JDK8的ConcurrentHashMap相对于JDK7来说,锁的粒度变小了,也就是说并发性更大了。用了synchronized+CAS代替了ReentrantLock ,数据结构也简单了一些。
贴一下盗的图:

201910301005\_3.png

1.8-1.png

从图上可以看出,数据结构相对比较简单,主要由数组与链表+红黑树组成,锁的粒度就是各个链表首节点。

总结

  1. 锁粒度:

JDK8的锁粒度相比于JDK7降低了,JDK1.7版本锁的粒度是基于Segment的,包含多个HashEntry,而JDK1.8锁的粒度就是HashEntry(首节点).

  1. 代码复杂度

JDK8的虽然去掉了分段锁的概念,即数据结构变得简单了,但是相应的代码复杂度就上来了,比如红黑树

  1. 锁的方式

JDK8采用synchronized+CAS代替了ReentrantLock,这块的原因可能就是synchronized比较受重视。

  • 因为粒度降低了,在相对而言的低粒度加锁方式,synchronized并不比ReentrantLock差,在粗粒度加锁中ReentrantLock可能通过Condition来控制各个低粒度的边界,更加的灵活,而在低粒度中,Condition的优势就没有了。
  • 基于JVM的synchronized优化空间更大,使用内嵌的关键字比使用API更加自然。
  • 在大量的数据操作下,对于JVM的内存压力,基于API的ReentrantLock会开销更多的内存。

参考资料

http://ifeve.com/concurrenthashmap/
https://baijiahao.baidu.com/s?id=1617089947709260129&wfr=spider&for=pc
http://www.importnew.com/26049.html
http://www.importnew.com/28263.html


来源:https://www.jianshu.com/p/a75d196731c0

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » JAVA并发容器源码分析【二】ConcurrentHashMap分析之数据结构(JDK7与JDK8)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏