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
相关产品推荐
相关产品推荐

