为什么Java中的非线程安全计数器总是返回正确的值?



我试图通过增加执行器服务任务中的计数来模拟非线程安全计数器类,并使用倒计时锁存器等待所有线程启动,然后在主线程中读取值之前停止。

问题是,当我运行它的系统。最后的Out总是返回10作为正确的计数值。我希望看到一些其他的值,当我运行这个10个线程可能会看到不同的值。

我的代码如下。知道这里发生了什么吗?我在Java 17和Intellij IDEA中运行它。

Counter.java

public class Counter {
private int counter = 0;
public void incrementCounter() {
counter += 1;
}
public int getCounter() {
return counter;
}
}

Main.java

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
CountDownLatch startSignal = new CountDownLatch(10);
CountDownLatch doneSignal = new CountDownLatch(10);
Counter counter = new Counter();
for (int i=0; i<10; i++) {
executorService.submit(() -> {
try {
startSignal.countDown();
startSignal.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
counter.incrementCounter();
doneSignal.countDown();
});
}
doneSignal.await();
System.out.println("Finished: " + counter.getCounter());
executorService.shutdownNow();
}
}

值得记住的是,仅仅因为某些东西没有正确同步,它在某些情况下仍然可以正确执行,只是不能保证在每种情况下,在每种JVM上,在每种硬件上。

换句话说,没有反向保证,例如优化器可以自由地决定你的代码可以用正确同步的实现以很少或没有成本的方式替换。

(我第一眼看不出这是不是真的)