Java并发编程之ConcurrentHashMap(三)

2014-11-24 09:12:25 · 作者: · 浏览: 2
ull;
13
if (e != null) {
14
V v = e.value;
15
if (value == null || value.equals(v)) {
16
oldValue = v;
17
// All entries following removed node can stay
18
// in list, but all preceding ones need to be
19
// cloned.
20
++modCount;
21
HashEntry newFirst = e.next;
22
for (HashEntry p = first; p != e; p = p.next)
23
newFirst = new HashEntry(p.key, p.hash,
24
newFirst, p.value);
25
tab[index] = newFirst;
26
count = c; // write-volatile
27
}
28
}
29
return oldValue;
30
} finally {
31
unlock();
32
}
33
}
首先remove操作也是确定需要删除的元素的位置,不过这里删除元素的方法不是简单地把待删除元素的前面的一个元素的next指向后面一个就完事了,我们之前已经说过HashEntry中的next是final的,一经赋值以后就不可修改,在定位到待删除元素的位置以后,程序就将待删除元素前面的那一些元素全部复制一遍,然后再一个一个重新接到链表上去,看一下下面这一幅图来了解这个过程:

假设链表中原来的元素如上图所示,现在要删除元素3,那么删除元素3以后的链表就如下图所示:

ConcurrentHashMap的size操作
在前面的章节中,我们涉及到的操作都是在单个Segment中进行的,但是ConcurrentHashMap有一些操作是在多个Segment中进行,比如size操作,ConcurrentHashMap的size操作也采用了一种比较巧的方式,来尽量避免对所有的Segment都加锁。

前面我们提到了一个Segment中的有一个modCount变量,代表的是对Segment中元素的数量造成影响的操作的次数,这个值只增不减,size操作就是遍历了两次Segment,每次记录Segment的modCount值,然后将两次的modCount进行比较,如果相同,则表示期间没有发生过写入操作,就将原先遍历的结果返回,如果不相同,则把这个过程再重复做一次,如果再不相同,则就需要将所有的Segment都锁住,然后一个一个遍历了,具体的实现大家可以看ConcurrentHashMap的源码,这里就不贴了。