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

使用AtomicInteger实现共享计数器并发自增的异常问题排查

为什么AtomicInteger自增后线程输出结果不一致?

你的代码里,AtomicInteger的incrementAndGet()确实是原子操作,所以共享计数器的最终值肯定是20000,但输出结果不一致的问题出在return的时机:

  • 两个线程并发执行incrementCounter()方法,每个线程都会循环10000次调用原子自增。
  • 假设线程t1先跑完10000次自增,此时它会立刻调用sharedCounter.get()返回当前值——这时候线程t2可能已经执行了一部分自增(比如3000次),所以t1返回的就是10000+3000=13000。
  • 等t2把剩下的7000次自增做完,再调用get()的时候,计数器已经被两个线程总共增到20000了,所以t2返回20000。
  • 反过来,如果t2先跑完自己的循环,t1还在执行,那t2返回的就是10000加上t1已经完成的次数,t1最后返回20000。

另外要说明:你给AtomicInteger加的volatile是多余的——AtomicInteger内部通过Unsafe类的CAS操作已经保证了值的可见性和原子性,不需要额外用volatile修饰。

如果想让两个线程都输出20000,可以调整代码逻辑:不要在每个线程的方法里返回并输出,而是等两个线程都执行完毕后,在main方法里统一获取并打印最终值:

class MyCounterClass{
    AtomicInteger sharedCounter = new AtomicInteger(0);

    public void incrementCounter() {
        for(int i = 0; i <10000; i++){
            sharedCounter.incrementAndGet();
        }
    }
}

public static void main(String[] args) throws InterruptedException {
    MyCounterClass myCounterClassObj = new MyCounterClass();
    Thread t1 = new Thread(myCounterClassObj::incrementCounter);
    Thread t2 = new Thread(myCounterClassObj::incrementCounter);

    t1.start();
    t2.start();

    t1.join();
    t2.join();

    // 所有线程执行完后再获取最终值
    System.out.println("最终计数器值:" + myCounterClassObj.sharedCounter.get());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:57:50