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

关于synchronized保证A对象线程安全的技术咨询

问题

在B类中定义了一个使用synchronized关键字的方法,该方法操作一个公开可用的A类对象。想咨询以下几个问题:

  1. 这种情况下A对象的线程安全是否能得到保障?
  2. synchronized作用于B的实例而非A对象(synchronized(this)等同于锁定B实例),这个理解对吗?
  3. 是否需要使用synchronized(a)代码块来提升线程安全性?
  4. 实际中第一种写法仍不具备线程安全性,即便这是修改该公开对象的唯一方法,原因是什么?

相关代码示例:

// 写法1:同步方法
public class B {
    public synchronized void updateA(A a) {
        // 操作a的逻辑
    }
}

// 写法2:同步B实例的代码块
public class B {
    public void updateA(A a) {
        synchronized (this) {
            // 操作a的逻辑
        }        
    }
}

// 写法3:同步A对象的代码块
public class B {
    public void updateA(A a) {
        synchronized (a) {
            // 操作a的逻辑
        }        
    }
}
分析与解答

直接给结论:写法1和写法2都无法保障A对象的线程安全,只有写法3能有效保护对A对象的操作。下面逐个拆解细节:

关于synchronized锁定对象的理解

你的判断是对的:

  • 写法1的synchronized方法,本质就是锁定当前B类的实例,和写法2的synchronized(this)逻辑完全一致。
  • 这两种写法锁的都是B的实例,而非传入的A对象。

写法1/2线程不安全的核心原因

哪怕updateA是修改A对象的唯一方法,只要出现以下场景,线程安全就会失效:

  1. 多个B实例操作同一个A对象:比如线程1用B1实例调用updateA(a),线程2用B2实例调用updateA(a)。B1和B2是不同的对象,各自的锁互不干扰,两个线程会同时进入方法操作同一个A对象,必然出现并发问题。
  2. 外部直接操作A对象:因为A是公开可用的,哪怕你只通过B的方法修改A,只要别的线程能直接拿到A的引用并修改(比如直接调用a.setXXX(...)),这些操作不受B实例锁的约束,同样会破坏线程安全。

写法3能保障线程安全的原因

写法3直接锁定A对象本身:

  • 不管是通过哪个B实例操作A,只要操作A的代码都用synchronized(a)包裹,就能保证同一时间只有一个线程能修改这个A对象。
  • 如果其他地方也要操作A,只要同样遵循锁定A对象的规则,就能整体保障A的线程安全。

额外提醒

如果A对象本身是不可变的,那不需要任何同步;但如果是可变对象,所有修改和读取A的操作都必须在同一个锁(也就是A对象本身)的保护下,才能真正实现线程安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:45:24