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

Java中synchronized锁Integer类型count失效但锁this正常问题咨询

问题原因分析

两种锁对象的核心差异

  • 锁为this的场景:你代码中两个线程t1、t2共享同一个Multi类实例r1,this始终指向这个唯一的r1实例,所有线程竞争的是同一个固定锁对象,因此同步块可以保证每次只有一个线程进入修改count,最终累加结果正确为200000。
  • 锁为Integer count的场景:Integer是不可变类,类内存储数值的value字段被final修饰,无法修改。你写的count++本质是三步操作:先将Integer拆箱为int值、执行+1计算、再自动装箱为新的Integer对象赋值给count变量。也就是说每执行一次count++,count指向的对象就会更新为新的实例,锁对象全程在动态变化,两个线程竞争的不是同一个锁,同步逻辑自然失效。

同步失效的具体执行逻辑

举个简单的执行序列说明:

线程1首先获取到当前count(值为10)的对象锁,进入同步块执行count++,执行结束后count指向了值为11的新Integer对象,随后线程1释放的是旧的、值为10的对象锁;此时线程2尝试获取锁,直接拿到了新的、值为11的对象锁,完全不会被线程1的旧锁阻塞,两个线程就会出现同时修改count的情况,累加操作出现丢失更新,最终结果就是不符合预期的随机值。

可行的修复方案

  • 方案1:保留注释中的this作为锁对象,锁实例全程固定,可保证同步有效性。
  • 方案2:定义专用的不可变锁对象,是行业推荐的最佳实践,代码示例如下:
class Multi extends Thread {
    Integer count = new Integer(0);
    // 定义专用的final锁对象,不会被修改
    private final Object lock = new Object();
    @Override
    public void run() {
        for(int i=0;i<100000;i++) {
            synchronized (lock) {
                count++;
            }
        }
        System.out.println(Thread.currentThread().getName() + "  "+count);
    }
}
  • 方案3:直接使用JUC包下的原子类AtomicInteger实现累加,不需要额外加同步锁,性能更高:
class Multi extends Thread {
    AtomicInteger count = new AtomicInteger(0);
    @Override
    public void run() {
        for(int i=0;i<100000;i++) {
            count.incrementAndGet();
        }
        System.out.println(Thread.currentThread().getName() + "  "+count.get());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:45:04