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

Java多线程未使用synchronized,实例变量为何仍能得到准确值?

为什么无synchronized时counter1最终值仍为200000?

这只是偶然的巧合,不是必然结果,核心原因是测试代码里的隐性同步和线程调度的随机性:

1. System.out.println的隐性同步

你代码里每次自增后都调用了println,而JDK中PrintStream的println方法内部自带synchronized同步块:

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

这意味着线程执行println时会被阻塞,相当于间接给counter1++加了同步约束,大幅降低了两个线程同时操作counter1的概率,让你测出了“正确”结果。

2. 线程调度的随机性

Java线程调度由JVM和操作系统决定,你的测试中可能刚好没出现counter1++的交错执行。counter1++本质是三步原子操作:

  • 从主存/缓存读取counter1当前值
  • 对值执行+1运算
  • 将新值写回主存/缓存

如果没有同步,两个线程可能同时读取到同一个旧值,各自加1后写回,会导致一次自增“丢失”,最终值小于200000。但你的测试里线程切换时机刚好避开了这个场景,所以结果正确。

3. 不可依赖的CPU缓存同步

即使没有显式同步,CPU也可能在某些时刻自动将缓存值刷回主存,让线程读到最新值,但这种行为完全不可控,不能作为线程安全的保障。

正确的线程安全做法

要确保counter1最终值一定是200000,有两种可靠方式:

  • 用synchronized包裹counter1++操作(即你注释掉的代码)
  • 使用java.util.concurrent.atomic.AtomicInteger替代int,它的incrementAndGet()方法是原子性的:
private AtomicInteger counter1 = new AtomicInteger(0);

public void incCounter1() {
    int value = counter1.incrementAndGet();
    System.out.println("Inside incCounter1, counter1 = " + value);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:41:17