对于java的线程安全容器类,除了HashTable外,jdk还提供了一种高效的实现方式,ConcurrentHashMap.
在jdk1.7之前,ConcurrentHashMap的底层实现维护了一个Segment类,默认值是16个.这个默认值也是ConcurrentHashMap的默认并行数量.在添加操作时,首先使用hash算法判断出当前的值对应的,然后通过cas保证对segment类的操作是线程安全的.
![1.7的实现方式](https://img-blog.csdnimg.cn/20200517205832910.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTExMTIwOA==,size_16,color_FFFFFF,t_70#pic_center)
在java8以后,jdk对这个操作进行了优化.不再使用segment作为中间的线程安全保证,继续使用和hashMap相同的结构,即数组加链表的结构,不过对于线程安全与效率是这样保证的.对于数组,如果数组还没有初始化,初始化数组.如果数组已被初始话,数组上的元素为空,则使用cas操作将put的元素放在数组上,如果数组上已经有元素了,则使用synchronized加锁保证对于这个位置的元素操作是线程安全的.
这是jdk的源码.
` if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else if (onlyIfAbsent // check first node without acquiring lock
&& fh == hash
&& ((fk = f.key) == key || (fk != null && key.equals(fk)))
&& (fv = f.val) != null)
return fv;
else {
V oldVal = null;
synchronized (f) {在这里插入代码片`
JAVA高并发容器类ConcurrentHashMap底层原理
最新推荐文章于 2024-10-06 20:16:20 发布