据我所知,当尝试从多个线程执行相同的操作时,Java并发API中的原子类操作是依次执行的,因此以下程序的输出对我来说似乎不一致。
我知道我可以通过使用同步块来生成我期望的输出,但我需要解释为什么不仅使用原子变量就能生成期望的输出。
我的推理是这样的-无论线程执行的顺序如何,它都会在另一个线程递增和打印原子变量值之前递增和打印。
public class VisitorCounterAtomic {
private AtomicInteger visitorCount = new AtomicInteger(0);
public void visitAndPrint() {
System.out.println("Total Visitors: " + visitorCount.incrementAndGet());
}
public static void main(String... args) {
ExecutorService service = null;
VisitorCounterAtomic counter = new VisitorCounterAtomic();
try {
service = Executors.newFixedThreadPool(20);
for (int i = 0; i < 10; i++)
service.submit(() -> counter.visitAndPrint());
} finally {
if (null != service) service.shutdown();
}
}
}
输出:
Total Visitors: 1
Total Visitors: 4
Total Visitors: 2
Total Visitors: 5
Total Visitors: 3
Total Visitors: 6
Total Visitors: 7
Total Visitors: 8
Total Visitors: 9
Total Visitors: 10
我的期望输出:
Total Visitors: 1
Total Visitors: 2
Total Visitors: 3
Total Visitors: 4
Total Visitors: 5
Total Visitors: 6
Total Visitors: 7
Total Visitors: 8
Total Visitors: 9
Total Visitors: 10
我知道我可以通过使用同步块来生成我期望的输出,但我需要解释为什么不仅使用原子变量就能生成期望的输出。
我的推理是这样的-无论线程执行的顺序如何,它都会在另一个线程递增和打印原子变量值之前递增和打印。
visitorCount.incrementAndGet()
的调用是按顺序执行的。然而,线程的启动并不保证以任何特定的顺序发生。当调用线程的start()
方法时,该线程的 Runnable 将在稍后的某个时间执行。确切的时间取决于操作系统。 - VGR