能否直接更新其他对象的volatile变量?是否需调用同步方法?
直接修改volatile变量是否安全?还是应当调用同步方法?
首先给出定义的Some类:
class Some { synchronized void some() { // 基于canceled变量执行操作 } synchronized void setAsCanceled() { canceled = true; } volatile boolean canceled = false; // 包访问权限 }
另有Other类直接修改Some对象的canceled变量,而非调用setAsCanceled()方法:
class Other { void setSomeAsCanceled() { some.canceled = true; // 未调用setAsCanceled() } private Some some = new Some(); }
问题分析
直接修改volatile变量的安全性
从线程可见性的角度来说,直接修改这个volatile变量是安全的。因为volatile关键字的核心语义就是保证变量的修改对所有线程立即可见:写操作会立刻将值刷新到主内存,读操作会直接从主内存读取,不会依赖线程本地缓存,所以执行some()方法的线程能及时看到canceled的变化,不会出现缓存不一致导致的逻辑错误。
为什么更推荐调用setAsCanceled()同步方法
虽然直接修改volatile变量能保证可见性,但更建议调用setAsCanceled()方法,原因如下:
- 封装性原则:面向对象设计中,类的内部状态应该由类自身的方法来管控,外部代码直接访问修改成员变量会破坏封装,导致代码耦合度升高。如果后续
Some类需要扩展setAsCanceled()的逻辑(比如添加通知等待线程的操作、修改其他关联变量等),直接修改canceled的外部代码会错过这些逻辑,引发不一致问题。 - 扩展性与原子性保障:当前
setAsCanceled()只是简单设置canceled为true,但同步方法持有对象锁。如果未来该方法需要添加其他操作(比如修改非volatile的成员变量),同步锁可以保证整个方法内的操作是原子性的,而直接修改canceled无法提供这种原子性保障,可能引发新的线程安全问题。
内容的提问来源于stack exchange,提问作者Jin Kwon
相关产品推荐
相关产品推荐

