У меня есть фрагмент кода, который изменяет счетчик в двух потоках. Это не потокобезопасно, потому что я не поместил ни одной атомарной переменной или блокировки в коде. Это дает правильный результат, как я и ожидал, если код запускается только один раз, но я хочу запустить его несколько раз, поэтому я поместил код в цикл for. И вопрос в том, что только первый или первые два цикла дадут ожидаемый результат. Для остальных циклов результаты всегда равны 0, что кажется поточно-ориентированным. Есть ли какой-либо внутренний оператор в виртуальной машине Java, приводящий к такой вещи?
Я попытался изменить количество циклов, и первые один или два всегда соответствуют ожидаемым, но остальные равны 0 независимо от того, сколько существует циклов.
Счетчик:
private static class Counter {
private int count;
public void increase() {
count++;
}
public void decrease() {
count--;
}
public int getCount() {
return count;
}
}
Человек:
// This is just a thread to increase and decrease the counter for many times.
private static class Person extends Thread {
private Counter c;
public Person(Counter c) {
this.c = c;
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
c.increase();
c.decrease();
}
}
}
Основной метод:
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
Counter c = new Counter();
Person p1 = new Person(c);
Person p2 = new Person(c);
p1.start();
p2.start();
p1.join();
p2.join();
System.out.println("run "+i+": "+c.getCount());
}
}
Выход:
run 0: 243
run 1: 12
run 2: 0
run 3: 0
run 4: 0
run 5: 0
run 6: 0
run 7: 0
run 8: 0
run 9: 0
Я не знаю, почему остальные результаты всегда равны 0. Но я думаю, что это оптимизация JVM. Правильно ли, что JVM оптимизирует код, когда некоторые циклы выполнены, и пропускает остальные циклы и всегда дает 0 в качестве ответа?