JUC1.8-ConcurrentHashMap学习总结-如果我是面试官,我会问哪些面试题?

前言

从9月初,开始写博客开始,因笔者平时也是有工作,陆陆续续经过一周多时间,从学习-》解析-》分析 ,并发包中的第一个并发容器ConcurrentHashMap为止。 过程中确实很花费精力,十分枯燥,也有在某一点上死钻牛角尖的时候,导致一度都想打退堂鼓。 但还是得坚持,慢慢用debug方式,逐行去剖解,分析作者的意图, 每当想明白一个难点时,感觉之前的枯燥呀,烦躁呀,一扫而空,美滋滋。 那么今天就来对ConcurrentHashMap做一次总结。

写作方面:

在开立博客时,笔者写过一篇自己学习的方法论,目前感觉良好:

  1. 一定得先阅读官方的文档。了解清楚这个玩意有啥功能,有啥特征,然后由面到点。

  2. 根据咱们平时常用的一些API,逐一展开学习跟踪源码。 学习某个API的时候,也是由面到点,通读文档后,先凭借自己阅码能力,看一遍,把看不明白的代码板块做标记, 其次是脑袋不能空看,得在阅码时,自己去发现问题,心里多一些为什么,为什么。 ok,有些人肯定会说,我问不出来怎么办? 最简单方法,在API源码中,有常量体现的地方,咱们就从对常量理解入手,想为什么是如此设定,由此为线索,慢慢抽丝剥茧。 最后是在看不明白的地方,通过代码debug方式,分析。

  3. 最后就是得坚持,每次看完后,把自己所思考的精华记下来,这些就是最宝贵的财富。

源码方面:

每一次的总结都意味着重新开始, 肯定没有结束。 ConcurrentHashMap确实是非常的璀璨,笔者也只是阅码了几个常用的方法,其精华部分还需要自我慢慢在消化吸收,同时也为我在后期学习中,指明了一些良好的思考思路。 不多说,笔者把前面几篇学习的文档按照优先级放出来,肯定有理解不对或者思考透的地方,也请大家不吝赐教,也可以通过下图方式,联系我,咱们一起在盘码的路上走起;

JUC1.8-ConcurrentHashMap源码学习-准备 是盘码预前了解篇,其内容包含了 “位运算”、“转二进制”,“CAS原理理解”,“Java内存模型理解”。 对以上内容烂于心的同学可以略过;

思考点:
在JDK源码中,大多采用位运算的方式,因此咱们对于二进制转换和相关位运算【& | ~ << >> >>>】必须得掌握,否者会给阅读带来一定阻碍;
其次针对Java内存模型来说,是一个过程的学习。 如果想学好并发包的源码,那么这个模型一定得烂于心。并发就是针对 原子、有序、可见,三大特性来处理,所以不搞明白底层原理是啥,就想去看表面东西,那不是在瞎扯嘛。

以下4篇按照由上之下即可,由putVal为入口,在到扩容的为结束的学习路程:
JUC1.8-ConcurrentHashMap源码学习-putVal()方法
JUC1.8-ConcurrentHashMap源码学习-容量是2次幂以及如何保证是2次幂
JUC1.8-ConcurrentHashMap源码学习-扩容方法解析transfer()
JUC1.8-ConcurrentHashMap源码学习-为什么每次扩容是原来两倍?

思考点:
putVal方法:

  1. 不允许key 和 val为null
  2. 使用CAS算法,volatile,synchronized三个方式确保线程安全,其中synchronized仅用于某节点,锁颗粒更小。
  3. 新增sizeCtl变量,用于对map整的状态控制;
  4. init容器,是在第一次put时进行;
  5. hash冲突时,连用链表储存,放置尾部,长度达到8,转红黑树
  6. 每当增加数据后,通过addCount 方法,对 size 加一,在对其判断是否需要扩容。 判断条件容器长度 * 0.75
  7. 新增加ForwardingNode,标识扩容中。 其他put操作时,识别则可以帮忙扩容
  8. 扩容最大线程为65535,这是低 16 位的最大值限制的。
  9. 根据当前机器的CPU数,计算区间桶的处理数。 没有达到16, 默认用16一个区间桶;
  10. 新表在原表的基础上扩容2倍;
  11. 每个线程在处理当前区间桶后,如原表还有数据,则通过transferIndex减9中的处理数。
  12. 在put时,如在扩容节点,遇到fwd,那么加入扩容大军
  13. 转移数据,采用反序对数据进行高低位计算识别。最终拆分成高低位两条链表或者数;
  14. 转移数据过程中,也得准守链表转数,数转链表规则;
  15. 当所有数据转移完毕,默认在重新循环一次,一方有遗漏数据;

上面阅读感觉有难度,可以换个思路看下读操作,算是简单方法,看懂增强咱们自信心:
JUC1.8-ConcurrentHashMap源码学习-get()

思考点:

  1. 读没有加锁的原因:是采用CAS与volatile方式,但一定得注意,volatile Node是保证当前节点的可见,真正保证安全的是Node -> volatile val属性;
  2. 不同的数据结构,都有属于自己的find辅助查询;

如果我是面试官,我会问哪些问题?

我把阅读过程中,感觉比较隐匿的一些 知识点问题列出,如果我是面试官,问了这些问题,你能回答上来,那么我会真的认为你是真的研究技术:

1、put方法中,在哪些地方使用到同步锁,为什么要使用?
----考察你对源码流程的理解,以及相比JDK1.7中,并发性能做的提升;

2、Map是在何时做的初始化步骤:

3、接着上面问,初始化时怎么保证线程安全,不会重复初始化,初始化的容量怎么定义? 为什么容量一定是2的次幂?

4、聊聊是怎么协助扩容的? 扩容的机制是怎么样的? 扩容量为啥是原来的2倍?

5、读的时候,怎么保证线程安全?

上面几个方法答案,后面我在整理出来,相信这些问题对答如流,那么咱们对这个并发Map面试也算是及格了吧。 大家也可以在我前面的博客里面找找答案,给我留言。

后面笔者将开始对CopyOnWriteArrayList列为下一个攻克点,最后附上笔者联系方式,加好友时,请麻烦备注通过CSDN博客添加,欢迎大家来骚扰。?

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值