Java并发包探秘 (二) ConcurrentHashMap(三)

2014-11-24 01:45:23 · 作者: · 浏览: 3
源代码。

最后我们看看size操作的实现:

Java代码

public int size() {

final Segment[] segments = this.segments;

long sum = 0;

long check = 0;

int[] mc = new int[segments.length];

// Try a few times to get accurate count. On failure due to

// continuous async changes in table, resort to locking.

for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {

check = 0;

sum = 0;

int mcsum = 0;

for (int i = 0; i < segments.length; ++i) {

sum += segments[i].count;//1.注意这语句

mcsum += mc[i] = segments[i].modCount;//2.还有这一句。

//以上两句是不能调换位置的,还是JSR166 happens-before原则。count之前修改的内容一定会被读取到,jdk 1.5 volatile 关键字的语意增强。

}

if (mcsum != 0) {

for (int i = 0; i < segments.length; ++i) {

check += segments[i].count;

if (mc[i] != segments[i].modCount) {

check = -1; // force retry

break;

}

}

}

if (check == sum)

break;

}

if (check != sum) { // Resort to locking all segments

sum = 0;

for (int i = 0; i < segments.length; ++i)

segments[i].lock();//全部加锁

for (int i = 0; i < segments.length; ++i)

sum += segments[i].count;

for (int i = 0; i < segments.length; ++i)

segments[i].unlock();//全部解锁

}

if (sum > Integer.MAX_VALUE)

return Integer.MAX_VALUE;

else

return (int)sum;

}

RETRIES_BEFORE_LOCK 的默认值是2,2次循环检测看看modCount的数据是否一致,(modCount的值是只增不减的)一致说明此时没有并发修改。直接返回,否则进行全Segment的加锁计算。

总结:

并发HashMap是Java并发包中名气最大的并发容器。在刚刚发布不久的Java 7 中也有更新。当然仅仅只是版权和类结构上的优化。并没有从算法上更新,所以这里不做展开讨论。并发HashMap中将锁、hash算法和JSR166使用到了极致,是Java中不可多得的财富。只可学习不要轻易模仿。