You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java原子类并发疑问:多线程下程序输出为何不符合预期?

为啥你的AtomicInteger程序输出和预想的不一样?

兄弟,你对原子类的核心认知其实没错:AtomicInteger的incrementAndGet()这类原子方法,确实是靠CAS机制保证同一时间只有一个线程能成功执行,所以最终的计数绝对是准确的(比如10个线程跑下来,最大的数字肯定是10)。

那问题出在哪?看你写的代码,你把「原子计数」和「打印结果」拆成了两个独立操作——这俩加起来可不是原子的!

先把你没写完的代码补全,大概是这样对吧:

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;
        try {
            service = Executors.newFixedThreadPool(10);
            VisitorCounterAtomic counter = new VisitorCounterAtomic();
            for (int i = 0; i < 10; i++) {
                service.submit(counter::visitAndPrint);
            }
        } finally {
            if (service != null) service.shutdown();
        }
    }
}

举个具体场景你就懂了:

  • 线程A先抢到CPU,执行incrementAndGet()拿到了数字2,但还没来得及调用println;
  • 这时候线程B抢到CPU,执行incrementAndGet()拿到数字3,然后直接完成了打印;
  • 之后线程A才继续执行打印,结果控制台就先出现Total Visitors: 3,再出现Total Visitors: 2——看起来顺序乱了,但计数本身一点没错。

说白了,原子类只保证「计数」这一步是线程安全的,但不保证「计数+打印」整个流程的原子性。如果想要打印的顺序和计数的顺序完全一致,你得把这俩操作绑在一起,用同步锁包住:

比如给方法加synchronized关键字:

public synchronized void visitAndPrint() {
    int currentCount = visitorCount.incrementAndGet();
    System.out.println("Total Visitors: " + currentCount);
}

或者干脆不用AtomicInteger,直接用普通int加同步(效果一样):

private int visitorCount = 0;

public synchronized void visitAndPrint() {
    visitorCount++;
    System.out.println("Total Visitors: " + visitorCount);
}

另外提一嘴:System.out.println()本身是线程安全的(内部有同步块),但这只能保证打印的内容不会乱码,没法保证多个线程的打印顺序和它们执行计数的顺序一致——毕竟“拿数”和“打印”中间没加锁约束嘛。

内容的提问来源于stack exchange,提问作者iamcrypticcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:52:27