Eu tenho um trecho de código que mudar um contador em dois tópicos. Não é o segmento de seguros, porque eu não colocar qualquer variável atômica ou bloqueio no código. Ele dá o resultado certo como eu esperava se o código executado apenas uma vez, mas eu quero executá-lo por várias vezes, então eu coloquei o código em um loop. E a questão é que apenas o primeiro ou os dois primeiros ciclos irá gerar o resultado que eu esperava. Para o resto dos loops, os resultados são sempre 0, o que parece ser thread-safe. Existe alguma operador interno em Java Virtual Machine resultando tal coisa?
Eu tentei alterar o número de loops, eo primeiro um ou dois são sempre o que eu esperava, mas os outros são 0, não importa quantas voltas existem.
Contador:
private static class Counter {
private int count;
public void increase() {
count++;
}
public void decrease() {
count--;
}
public int getCount() {
return count;
}
}
Pessoa:
// 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();
}
}
}
método principal:
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());
}
}
Resultado:
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
Eu não sei por que o resto dos resultados são sempre 0. Mas eu acho que é sobre a otimização da JVM. É certo que a JVM otimiza o código quando alguns loops ter sido feito, e omite os loops de descanso e sempre dá 0 como resposta?
Eu acho que a JVM é otimizar aqui como você disse.
Eu adicionei algumas saídas com horários à sua pergunta, que mostram claramente, que a otimização acontece lá.
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
final long startTime = System.currentTimeMillis();
Counter c = new Counter();
Person p1 = new Person(c);
Person p2 = new Person(c);
p1.start();
p2.start();
p1.join();
p2.join();
final long endTime = System.currentTimeMillis();
System.out.println(String.format("run %s: %s (%s ms)", i, c.getCount(), endTime - startTime));
}
}
Resultados:
run 0: 1107 (8 ms)
run 1: 1 (1 ms)
run 2: 0 (2 ms)
run 3: 0 (0 ms)
run 4: 0 (0 ms)
run 5: 0 (0 ms)
run 6: 0 (1 ms)
run 7: 0 (0 ms)
run 8: 0 (0 ms)
run 9: 0 (0 ms)
As primeiras iterações o programa precisa de muito tempo, wheras em execução posterior quase nenhum momento a todos é usado.
Parece ser legítimo para optimazation suspeito para esse comportamento.
Usando um volatile int count
:
run 0: 8680 (15 ms)
run 1: 6943 (12 ms)
run 2: 446 (7 ms)
run 3: -398 (7 ms)
run 4: 431 (8 ms)
run 5: -5489 (6 ms)
run 6: 237 (7 ms)
run 7: 122 (7 ms)
run 8: -87 (7 ms)
run 9: 112 (7 ms)