Java synchronized() 关键字——防止字段中引用的对象发生变化?

标签 java multithreading concurrency

我知道

synchronized(objA) {
    objA.readSomething();
}

保护对象不被另一个线程修改。但是如果 objA 被声明为

class A {
    public B objB; 
    public void readSoemthing() {
       objB.readSomething();
    }
}

在接下来的代码块中,另一个 thead 调用 objB.modifySomething()?假设该线程以某种方式拥有自己对 objB 的引用。

那会安全吗?如果不是,处理它的正确方法是什么(即我不希望任何线程修改 A 内的任何内容,即使它是一个指向不同对象的字段,我也不希望该对象被修改)。

synchronized(objA) {
    objA.readSomething();  // at this point antoher thread calls objB.modifySomething()
}

最佳答案

您问题的第一部分不正确。 synchronized block 仅确保在执行 synchronized block 时,没有其他线程可以进入在 objA 引用的对象上也同步的代码块。

因此任何其他线程都可能同时修改 objA,除非所有修改 objA 的方法都是同步的。

既然你知道了,你也知道任何其他线程都可以从 objA 获取 objB 并用 objB 做任何它想做的事情,除非 objB 的所有方法也在 objA 上同步

这就是封装在线程安全类中至关重要的原因。所有访问(读取或写入)对象共享状态的方法都应该通过该对象的同步方法。并且共享状态永远不应该暴露给外部。

关于Java synchronized() 关键字——防止字段中引用的对象发生变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20076470/

相关文章:

smalltalk - Smalltalk中的图像间通信。可能的?

c - 如何在 C 中取消引用并使用传递给 POSIX 线程的矩阵?

java - 无状态 Bean 上的并发

Java 跳过最后一个变量

java - 在java中释放直接缓冲区以及可能的陷阱

c# - 锁变量应该声明为 volatile 吗?

Java Micro Edition - 使用线程和委托(delegate)进行 HTTP 发送/接收(如何更新 UI)

java - 使用 @AndroidFindBy 为具有多个 appPackage 的 android 运行 appium 测试

java - DLTK TCL 项目导入问题

java - 为什么当操作系统代表时java会承担线程切换的开销