Java多线程同步疑问:synchronized(this)为何无法保证结果为0?
问题解析与解决方案
嗨,我来帮你把这个问题掰明白~
首先,你调试发现的this对象始终不同,就是导致结果不对的核心原因!
为什么this会不一样?
你创建两个线程时,分别用了两个独立的匿名Runnable内部类实例:
- 第一个线程的
Runnable是一个全新的对象,它的this指向自己这个Runnable实例; - 第二个线程的
Runnable又是另一个全新的对象,它的this指向自己的Runnable实例。
这就意味着两个线程的synchronized (this)其实是在锁完全不同的两把锁,相当于根本没起到同步的作用——两个线程可以同时对value进行读写操作。
为什么结果不是0?
虽然value被声明为volatile,但volatile只能保证变量的可见性(一个线程修改后,其他线程能立刻看到最新值),却不能保证操作的原子性。
++value和--value其实都包含三个步骤:
- 读取当前
value的值; - 对值进行加1/减1运算;
- 将运算结果写回
value。
当两个线程同时执行这三个步骤时,就会出现“竞态条件”:比如线程A刚读到value=5,还没来得及写回;线程B也读到了value=5,最后一个加1变成6,一个减1变成4,两者的操作就相互覆盖了,最终计数就会偏差。
怎么修复这个问题?
有两种常见的解决方案:
方案1:使用同一个共享锁对象
既然要同步对静态变量value的操作,我们可以定义一个全局共享的锁对象,让两个线程都锁这个对象:
public class Lesson6 { private static volatile Long value = 0L; // 定义一个静态的共享锁对象 private static final Object lock = new Object(); public static void main(String[] args) throws InterruptedException { Thread inc = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100_000; i++) { synchronized (lock){ // 锁同一个对象 ++value; } } } }); inc.start(); Thread dec = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100_000; i++) { synchronized (lock){ // 锁同一个对象 --value; } } } }); dec.start(); inc.join(); dec.join(); System.out.println(value); } }
方案2:使用原子类(更推荐)
Java的java.util.concurrent.atomic包提供了一系列原子操作类,比如AtomicLong,它的增减操作本身就是原子性的,不需要手动加锁:
import java.util.concurrent.atomic.AtomicLong; public class Lesson6 { // 用AtomicLong代替volatile Long private static final AtomicLong value = new AtomicLong(0L); public static void main(String[] args) throws InterruptedException { Thread inc = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100_000; i++) { value.incrementAndGet(); // 原子加1 } } }); inc.start(); Thread dec = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100_000; i++) { value.decrementAndGet(); // 原子减1 } } }); dec.start(); inc.join(); dec.join(); System.out.println(value.get()); } }
这样修改后,你就能得到预期的输出0啦~
内容的提问来源于stack exchange,提问作者Константин Крылов
相关产品推荐
相关产品推荐

