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

多线程计数器同步问题求助:AtomicInteger与普通变量同步异常

问题分析与解决

问题原因

你遇到的核心问题是线程执行时机的不确定性:

  • t1、t2、t3三个线程同时启动,t3的打印操作可能在t1、t2还没完成所有500次递增时就执行,所以每次打印的都是计数器的中间值,而非最终的1000。
  • 你提到注释掉atomicIntegers.increment()后a能得到正确1000,这只是偶然现象——某次运行中t1、t2刚好在t3开始打印前完成了所有递增,并非注释increment()本身解决了问题。线程调度不可控,这种偶然结果不具备通用性。

另外,你的AtomicIntegers类继承Thread属于冗余设计,它只是一个计数器工具类,完全不需要继承线程类。

解决方案

1. 确保t3在t1、t2执行完成后再打印

在启动t3前,调用t1和t2的join()方法,让主线程等待t1、t2执行完毕后再启动t3:

public static void main(String args[]) throws InterruptedException {
    AtomicIntegers atomicIntegers = new AtomicIntegers();
    Thread t1= new Thread() {
        @Override
        public void run() {
            for(int i =0; i<500; i++) {
                atomicIntegers.incrementBoth();
            }
        }
    };

    Thread t2= new Thread() {
        @Override
        public void run() {
            for(int i =0; i<500; i++) {
                atomicIntegers.incrementBoth();
            }
        }
    };

    Thread t3= new Thread() {
        @Override
        public void run() {
            System.out.println("atomicInteger最终值: " + atomicIntegers.getAtomicInteger());
            System.out.println("a最终值: " + atomicIntegers.getA());
        }
    };

    t1.start();
    t2.start();
    // 等待t1、t2执行完毕
    t1.join();
    t2.join();
    // 再启动t3打印最终结果
    t3.start();
}

2. 实现两个计数器的同步递增

要保证atomicInteger和a每次都同步递增(即单次操作同时更新两个值),需要把两个递增逻辑放在同一个同步上下文里,避免出现一个更新、另一个未更新的不一致情况:

// 重构工具类,去掉不必要的Thread继承
class AtomicIntegers {
    private AtomicInteger atomicInteger = new AtomicInteger(0);
    private int a = 0;
    private final ReentrantLock lock = new ReentrantLock();

    // 同步递增两个计数器
    public void incrementBoth() {
        lock.lock();
        try {
            atomicInteger.incrementAndGet();
            a++;
        } finally {
            lock.unlock();
        }
        // 也可以用synchronized块替代锁,效果一致
        // synchronized (this) {
        //     atomicInteger.incrementAndGet();
        //     a++;
        // }
    }

    public int getAtomicInteger() {
        return atomicInteger.get();
    }

    public int getA() {
        lock.lock();
        try {
            return a;
        } finally {
            lock.unlock();
        }
    }
}

修改后,t1、t2每次调用incrementBoth()都会同步更新两个计数器,t3则会在t1、t2完成所有操作后打印最终值,两个计数器的结果都会稳定为1000。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 22:12:08