今天再来说说JUC下的HashMap的put方法
上源码:
赶脚特别长是不是,其实拆解来看并没有很复杂。
没工夫的可直接滚轮最后查看完整注释版。
1、初始化变量,中间看到的initTable是不是很眼熟,就是之前讲的initTable 见第一Part
2、找到对应的位置 tabAt返回的是Node,也是Unsafe获取的,如果空就直接Cas插入啦。当然如果并发Cas是失败。失败后会在上一个for中继续重试
3、判断是否在扩容移动。这边扩容是concurrentHashMap的精华。我们日后详细分解
4、接下来就是位置上有值,使用synchronized 加锁,先判断是否是链表,如果是那就遍历去比较,发现相同的就会替换,如果没有那就在末尾追加。如果Node是红黑树那就调用红黑树。(ps:红黑树数据结构自行查阅资料,涉及不少知识。包括红黑树的结构,树的自平衡等等)
5、在完成上面的put后,就需要检查链表是不是需要转换成红黑树了
6、最后是元素统计
最后附上一张完整的注释截图。
总结:
ConcurrentHashMap的线程安全是如何保证的?
看到这里其实能够大概看到端倪,Doug lea大量使用了Unsafe的Cas的原子操作,并且使用了synchronized上锁,及volatile的同步来保证安全的。