После другого вопроса, заданного в stackoverflow, (Java- Почему эта программа не бросает параллельное исключение модификации) Я начал экспериментировать с HashMap. Вот несколько строк кода, которые я написал:
import java.util.HashMap;
import java.util.Random;
public class Concurrency {
public static void putEntriesToMap(HashMap<String, String> hashMap) {
for (int count = 0; count < 10000; count++) {
hashMap.put(Integer.toString(count), Integer.toString(count));
Random random = new Random();
if (random.nextBoolean()) {
hashMap.remove(count + "");
}
}
}
public static void main(String[] args) throws InterruptedException {
final HashMap<String, String> hashMap = new HashMap<String, String>();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
putEntriesToMap(hashMap);
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
putEntriesToMap(hashMap);
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
Когда-то (примерно 1 из 20 запусков) при выполнении этого кода я получаю
Exception in thread "Thread-0" Exception in thread "Thread-1" java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
at java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1819)
at java.util.HashMap$TreeNode.treeify(HashMap.java:1936)
at java.util.HashMap.treeifyBin(HashMap.java:771)
at java.util.HashMap.putVal(HashMap.java:643)
at java.util.HashMap.put(HashMap.java:611)
at Concurrency.putEntriesToMap(Concurrency.java:9)
at Concurrency$1.run(Concurrency.java:27)
at java.lang.Thread.run(Thread.java:745)
Это, однако, кажется мне странным, потому что похоже, что это внутренняя ошибка HashMap. Я знаю, что concurrency не используется правильно, но он сделан специально.
Я попытался сделать исключение Google, но я почти ничего не нашел.
Можно ли воспроизвести одно и то же исключение?
Я использую oracle jdk 1.8.0_40
EDIT:
Во-первых, спасибо за ответы, теперь это ясно для меня. Я просто хочу указать, что я знал, как избежать взлома программы, используя безопасные меры потока, но я не знал, почему именно это исключение выбрасывается в данной ситуации. Томас объяснил это очень хорошо в комментариях ниже. Это также хорошо объяснено в принятом ответе. Еще раз спасибо:).