第2次面试:某北方(2022-03-08)

  今天是女神节哈。先祝广大女神节日快乐,今天面试的是一家大型外包公司某北方。这是卡在两个问题上,而竟然是我比较擅长的领域:数据结构。
  问的是ConcurrentHashMap。HashMap的实现原理我肯定知道,但是更深的细节我也没回答出来。面试后的反思时间到。

ConcurrentHashMap实现原理

  ConcurrentHashMap源码呢?6000多行,以30行为一页,打印出来,有200页。如果看完,呵呵,这一个类呢,就得看上一个月。那咱这面试还要问其他问题呢?这学得完吗?所以需要有所省略,有所着重地去研究。

ConcurrentHashMap结构

  从结构上,ConcurrentHashMap是Node的数组,这个是和HashMap一样的。但是Node在HashMap中只有两个子类。而ConcurrentHashMap的Node有四个子类。那多出来的两个子类是干嘛用的?ForwardingNode是扩容时迁移用的。ReservationNode是compute方法时调用的。在compute方法执行过程中新建一个ReservationNode作为一个锁,并且替换掉原先的Node,是一种并发保护机制。而另外两种子类,TreeBin和TreeNode是用在红黑树的,TreeBin包含了红黑树的根,并且加上了一些用于并发的字段。

ConcurrentHashMap的锁

首先得讲ConcurrentHashMap的读方法是不加锁的,锁都加在写方法上。而锁用两种方式去做的,一种是synchronized关键字,二是CAS。锁的粒度在链表的头节点或者红黑树的TreeBin节点上。相对于JDK1.7,锁粒度更细。

ConcurrentHashMap的扩容

  ConcurrentHashMap的扩容在JDK8比JDK7进行了优化。优化点在于协助扩容。扩容是从table的最后一个索引开始的,每次转移开始就放置一个FordwardingNode,这个前面讲过。为了实现协助扩容,有个字段nextTable,这个时候不能用局部变量,因为局部变量其他线程不能访问。

HashMap的扩容因子为什么是0.75

  为什么是0.75,是基于空间和时间的考虑,选择了0.75。但更多的会问选择了0.75之后会怎么样。我看了源码才知道在扩容因子为0.75时,HashMap在table的每个索引上出现数据个数的概率服从 λ = 0.5 \lambda=0.5 λ=0.5的泊松分布。也就是服从以下分布公式:
e 0.5 × 0. 5 k k ! = 1 e × 1 2 k × 1 k ! = 1 e × 2 k × k ! \frac{e^{0.5}\times0.5^k}{k!}=\frac{1}{\sqrt e} \times \frac{1}{2^k}\times \frac{1}{k!}=\frac{1}{\sqrt e\times2^k\times k!} k!e0.5×0.5k=e 1×2k1×k!1=e ×2k×k!1
  也就是说假如HashMap的table为16个元素,采用0.75,就是放满时12个元素。是这个 3 / 4 3/4 3/4的比例觉得了那么每个桶(也就是数组位置),上出现k个点的概率为:
1 e × 2 k × k ! \frac{1}{\sqrt e\times2^k\times k!} e ×2k×k!1
  在JDK源码中写出了概率:

次数概率
00.60653066
10.30326533
20.07581633
30.01263606
40.00157952
50.00015795
60.00001316
70.00000094
80.00000006

  用数学期望来估算,近似的数学期望是每个位置0.3左右,那么16个位置大约总共是不到5个元素。因为最大12个元素有,所以总共13种情况。
0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 = 78 0+1+2+3+4+5+6+7+8+9+10+11+12=78 0+1+2+3+4+5+6+7+8+9+10+11+12=78
  平均下来 78 13 = 6 \frac{78}{13}=6 1378=6,比5大,但是这是拿16计算的,拿8或者32或其他数计算结果又不一样,所以这是一个总体的结果。而这个总体的结果,需要复杂的统计才能得到符合泊松分布的结论。这个计算过程我就不展开了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

醒过来摸鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值