Java中对象访问自身字段时是否需要使用synchronized方法?
关于对象访问自身字段是否需要synchronized方法的解答
Great question—this is a super common point of confusion when transitioning to multi-threaded Java code. Let’s break this down clearly using your example and core concurrency rules:
核心判断原则
不是所有字段访问都需要 synchronized,关键看这个字段是否会被多个线程并发读写。你的MyClass继承了Thread,显然是多线程场景,咱们结合你的代码来拆解:
为什么你的set/get用synchronized是合理的?
先看你的代码片段:
public class MyClass extends Thread { private PrintWriter printWriter; public synchronized void setPrintWriter(PrintWriter pw){ printWriter = pw; } public synchronized PrintWriter getPrintWriter(){ return printWriter; } }
这里的synchronized解决了两个关键问题:
- 可见性:如果其他线程调用
setPrintWriter修改了printWriter,当前线程(MyClass自己的run方法)调用getPrintWriter时,能立刻看到最新的字段值,不会因为线程本地缓存导致读取旧数据。 - 原子性:如果后续你在
setPrintWriter里添加更多逻辑(比如初始化PrintWriter缓冲区、设置编码),synchronized能保证这些操作作为一个整体执行,不会被其他线程打断。
什么时候不需要synchronized访问自身字段?
如果满足以下任一条件,同步完全是多余的:
- 字段只会被当前线程读写:比如
printWriter只在MyClass的run方法里初始化和使用,从来没有其他线程调用setPrintWriter。这种情况下不存在并发冲突,不需要同步。 - 字段是只读的:一旦初始化后就再也不会被修改,读取时不需要同步(建议用
final修饰,从语法上强制不可变)。
误区澄清:“对象访问自身字段”≠线程安全
很多人误以为对象自己操作自己的字段就不会有并发问题,这是错误的。举个场景:
- 线程A是MyClass的实例,在
run方法里读取printWriter; - 线程B同时调用同一个MyClass实例的
setPrintWriter修改字段;
如果没有同步,线程A可能读取到旧的printWriter引用,甚至出现不可预测的行为。
替代方案:用volatile修饰字段
如果你的setPrintWriter只是简单的引用赋值(没有额外逻辑),也可以用volatile关键字修饰printWriter:
private volatile PrintWriter printWriter;
volatile能保证可见性,但不保证复合操作的原子性。如果你的set方法有多个关联操作,还是用synchronized更稳妥。
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

