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

Java中非线程安全计数器为何总能返回正确值?

为什么非线程安全计数器在10线程递增后总能返回正确值?

你的代码里的Counter确实是非线程安全的——counter +=1本质是读取当前值→加1→写回新值三个非原子操作,多个线程同时执行时可能出现值覆盖,导致最终计数小于预期。但你没看到错误结果,原因在于:

1. 单次递增的竞争窗口极小

每个线程只执行一次递增操作,现代CPU执行这三个步骤的速度极快,10个线程的单次操作很难刚好在同一时间点竞争同一资源。线程切换本身也需要开销,10次操作可能在切换发生前就全部完成了,自然不会出现冲突。

2. 测试规模太小

仅10次递增的情况下,出现线程竞争的概率极低。就像扔10次硬币全是正面,不代表硬币没有反面,只是样本量不够,没触发小概率事件。

如何复现预期的错误

要触发线程安全问题,需要放大竞争概率,比如:

  • 让每个线程执行多次递增(比如1000次)
  • 增加线程数量
  • 在递增操作前后加入微小延迟,强制线程切换

修改后的Main代码示例:

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);
                }

                // 每个线程递增1000次,放大竞争概率
                for (int j = 0; j < 1000; j++) {
                    counter.incrementCounter();
                    // 可选:加入微小延迟,增加线程切换概率
                    // try { Thread.sleep(1); } catch (InterruptedException e) {}
                }
                doneSignal.countDown();
            });
        }

        doneSignal.await();
        System.out.println("Finished: " + counter.getCounter()); // 结果会小于10000
        executorService.shutdownNow();
    }
}

运行这段代码,你会发现最终计数大概率小于10000,这就是线程竞争导致的值覆盖问题。

总结

非线程安全的问题是概率性的,不是每次执行都会出现。你的初始测试场景因为操作次数少、执行速度快,刚好没触发竞争条件,但这不代表Counter是线程安全的。要验证线程安全问题,需要设计能放大竞争的测试用例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:01:13