JDK1.8 ConcurrentHashMap computeIfAbsentネストされたデッドロックバグ
10208 ワード
たまたまこのバグを見たので、メモしておきます
バージョンJDK 1.8(現在8 u 261までテストされているが、まだこの問題があるかどうかは不明である)、少なくとも1.9で が修復されたことは間違いない.シーンConcurrentHashMapにおけるcomputeIfAbsentの再ネストcomputeIfAbsent/putIfAbsent 現象スレッドデッドロック コード#コード#
Bug情報
コード#コード# public class CHMTest {
public static void main(String[] args) {
normal();
bug();
}
private static void bug(){
System.out.println("begin bug code ...");
Map<String, Integer> map = new ConcurrentHashMap<>(16);
System.out.println(map.size());
String hash1 = "AaAa";
String hash2 = "BBBB";
//hash ,
System.out.println("hash1:"+hash1.hashCode()+",hash1:"+hash2.hashCode());
map.computeIfAbsent(hash1, key -> {
map.putIfAbsent(hash2,1);
return 1;
});
System.out.println(map.size());
System.out.println("bug code is exec here?");
}
private static void normal(){
System.out.println("begin normal code ...");
Map<String, Integer> map = new ConcurrentHashMap<>(16);
System.out.println(map.size());
String hash1 = "AaAa";
String hash2 = "BBBB2";
System.out.println("hash1:"+hash1.hashCode()+",hash1:"+hash2.hashCode());
map.computeIfAbsent(hash1, key -> {
map.putIfAbsent(hash2,1);
return 1;
});
System.out.println(map.size());
System.out.println("begin normal code finished");
}
}
上記のコードを実行すると、bugメソッドブロックがデッドロックします.computeIfAbsentにcomputeIfAbsentまたはputIfAbsentをネストすると、2つのkeyに対応するhash値が同じでデッドロックが発生する
public class CHMTest {
public static void main(String[] args) {
normal();
bug();
}
private static void bug(){
System.out.println("begin bug code ...");
Map<String, Integer> map = new ConcurrentHashMap<>(16);
System.out.println(map.size());
String hash1 = "AaAa";
String hash2 = "BBBB";
//hash ,
System.out.println("hash1:"+hash1.hashCode()+",hash1:"+hash2.hashCode());
map.computeIfAbsent(hash1, key -> {
map.putIfAbsent(hash2,1);
return 1;
});
System.out.println(map.size());
System.out.println("bug code is exec here?");
}
private static void normal(){
System.out.println("begin normal code ...");
Map<String, Integer> map = new ConcurrentHashMap<>(16);
System.out.println(map.size());
String hash1 = "AaAa";
String hash2 = "BBBB2";
System.out.println("hash1:"+hash1.hashCode()+",hash1:"+hash2.hashCode());
map.computeIfAbsent(hash1, key -> {
map.putIfAbsent(hash2,1);
return 1;
});
System.out.println(map.size());
System.out.println("begin normal code finished");
}
}