什么是ConcurrentHashMap
以下观点都是建立在JDK1.8之上。
我们知道HashMap是非线程安全的,所以JDK给我们提供了几种线程安全的Map,HashTable
,Collections.SynchronizedMap
,ConcurrentHashMap
几种线程安全的Map来使用。HashTable
是每个方法都是synchronized修饰的。Collections.SynchroinzedMap
则是用一个Object来当锁,每个方法里都使用synchronized(obj)
来锁定。
这里没有理解以上的2种方法有什么区别,HashTable
是作用在方法上的,所以锁的是this对象,后者是锁的Object,有什么区别吗?
最后一种ConcurrentHashMap
则是使用了最新的锁技术来实现的。
实现原理
源码实现
变量
|
|
UnSafe相关
|
|
构造方法
|
|
构造方法都很类似,这里我只举例一个。
put方法
|
|
put方法总结:
存放对象的时候,第一次操作,会先初始化底层的数组对象,然后再进行后续的操作
在存放元素的时候有这么几种情况:
1.如果计算出的hash值与上数组长度得出的下标位置为null,则可以直接插入
2.如果当前元素的hash值为MOVED,就证明有线程在进行扩容,就帮助一起扩容
3.都没有的情况下,证明当前下标存在其他元素,则进入元素追加,如果是链表就进行链表的操作,如果是树,就进行树的操作,最后添加元素完成。
4.添加完元素,如果需要进行树的转换,进行转换。
5.增加计数器,完成所有操作。
treeifyBin方法
|
|
treeifyBin方法总结:
如果当前数组长度小于64,则不进行树元素的转换,直接扩容成2倍,如果不是的话,那就对节点进行转换,从链表节点,转换为树节点。
tryPresize方法
|
|
tryPresize方法总结:
这里就是对数组的一些异常情况做了兼容处理,最终保证扩容完成。
transfer方法
|
|
transfer方法总结:
>
addCount方法
|
|