昨天接到搜狐技术面试的电话,其中有问道这样一个问题:
ConcurrentHashMap会不会死锁?
当时想的是,ConcurrentHashMap的读是没有加锁的,写是有锁的,应该不会死锁。
然后被告知,是会发生死锁的。
于是回来之后,就开始看源码,百度,Google相关的问题。
找到最贴近的问答:http://stackoverflow.com/questions/3292577/is-it-possible-for-concurrenthashmap-to-deadlock
但是这个问题是10年提出来的,JDK用的是1.5的,后面提问者将JDK升级到1.6之后,好像就可以了。
另外一个问题 http://rainshow.iteye.com/blog/245769 也是用的JDK 1.5,并未找到原因。
另外相关的答案,大意都是说ConcurrentHashMap多段加锁要保持顺序,否则会发生死锁。但这个是JDK内部的实现,我们在使用的时候,并不需要做额外的操作。
关于ConcurrentHashMap死锁的问题,大概只能搜到这些相关的结果。
OK,我的问题如下:
JDK 1.5的ConcurrentHashMap是否会发生死锁?如果会,在什么样的情况下会?1.6之后是否修复了该问题?
跪求大神指点解惑,感激不尽......
PS1:我在JDK8的ConcurrentHashMap的size方法中看到如下代码:
CounterCell[] as = counterCells; CounterCell a;
long sum = baseCount;
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
}
return sum;
}
加菜: 为何要用a,而不是直接使用as[i] ?
PS2:技术面试官知识面很广,而且对部分技术研究很深。重要的,是她人很nice,亲和力很强。难道搜狐的妹子都如此优秀,压力山大呀。。。
PS3:难道你们只看到了妹子没有看到问题嚒?问题已高亮......
TO @令飞 了解嚒?
TO@红薯 大家都不严肃答题,肿么办?
这个是底层操作系统不同造成的 ,只发生在
详情查看,http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6822370
大概因为,线程在等待一个没有线程持有的锁时被挂起(Solaris 10中)。
另外我认为面试你的人的意思是使用ConcurrentHashMap后还需不需要其他的同步业务策略,不恰当的使用同步工具也会造成死锁,但是因为没有使用同步策略造成的。
JDK6以上已经修复
我想我可以回答第二个为什么使用a,而不是使用as[i]的问题:
多线程中,如果要在同一个方法里面,两次使用成员对象、方法返回值,就必须在这种方案或者加锁两种方案中选择一个:
通常而言,method2的行为是不希望的,使用临时变量保存就可以简单避免问题,如果不使用临时变量,就要对所有赋值给o的地方和读取两次o的方法进行加锁。与临时变量保存方法相比,孰优孰劣一目了然。
sumCount方法中的as和a的作用都是如此,as要用两次,a(即as[i])也要用两次,使用临时变量,简单快捷高效。
PS:有人可能会问,赋值操作并不是原子操作,在赋值处是否需要加锁,答案是不需要的。
什么,是妹子!!