Java 最终vs volatile guaranntee w.rt安全发布对象
摘自《Java并发实践》一书: 要安全地发布对象,两个 对对象和对象的引用 必须使对象的状态对用户可见 同时使用其他线程。A. 正确构造的对象可以 安全出版人:Java 最终vs volatile guaranntee w.rt安全发布对象,java,java-memory-model,Java,Java Memory Model,摘自《Java并发实践》一书: 要安全地发布对象,两个 对对象和对象的引用 必须使对象的状态对用户可见 同时使用其他线程。A. 正确构造的对象可以 安全出版人: 从静态初始值设定项初始化对象引用 将对它的引用存储到volatile字段或原子引用中 将对它的引用存储到正确构造的 反对 将对它的引用存储到由 锁 我的问题是: 要点2和要点3之间有什么区别?我对volatile方法和final方法在对象安全发布方面的差异感兴趣 他所说的第三点中正确构造的物体的最终场是什么意思?在开始项目符号点之前
- 从静态初始值设定项初始化对象引用
- 将对它的引用存储到volatile字段或原子引用中
- 将对它的引用存储到正确构造的 反对
- 将对它的引用存储到由
锁
volatile
方法和final
方法在对象安全发布方面的差异感兴趣李>
this
引用转义)。但他们为什么再次提到正确构造的对象呢
基本上意味着对该字段的任何写入都可以从其他线程看到。因此,当您将字段声明为volatile时:volatile
private volatile SomeType字段代码>,则可以保证如果构造函数写入该字段:
field=newsometype()代码>,此分配将由随后尝试读取
字段的其他线程可见
具有非常相似的语义:您可以保证,如果您有final字段:final
对该字段的写入(在声明或构造函数中):private final SomeType字段
field=newsometype()如果对象已正确发布,则代码>将不会重新排序,并且将被其他线程看到(例如,
的转义)this
this
从构造函数中转义,那么最终语义提供的保证就消失了:观察线程可能会看到具有默认值的字段(对象为null)。如果对象构造正确,则不会发生这种情况
人为的例子:
class SomeClass{
private final SomeType field;
SomeClass() {
new Thread(new Runnable() {
public void run() {
SomeType copy = field; //copy could be null
copy.doSomething(); //could throw NullPointerException
}
}).start();
field = new SomeType();
}
}
发布
volatile
与final
的效果没有区别,只是final
只能在构造函数中设置一次,因此您读取的内容永远不会更改
我相信正确构造的对象确实是您所指的对象,其
此
引用没有逃逸其构造函数,并且已以安全的方式发布到所使用的线程中。如果在构造之后,我更改由字段引用的对象的状态,如field.setX(new X())
,当我们将其声明为volatile时,这种更改是否也保证了其他线程可以看到?或者它只提供初始化安全性?在这种情况下,final如何?不,只有字段
为您提供了(重新)分配的可见性保证。除非x
也是易变的,field.x=new x()
(或您的setter示例)不提供这样的保证。final也一样,如果字段
的所有成员也是final并且是不可变的,字段
是不可变的,因此是线程安全的。@assylias我读了几遍您的答案,但仍然无法得到它。既然字段是最终的,就不会有任何重新排序,为什么新线程看不到“this”的“field”属性呢?你是说,这是因为构造函数还没有完成吗?当使用final
字段时,你甚至有了更多的保证:“[另一个线程]还将看到那些final字段引用的任何对象或数组的版本,它们至少与final字段一样是最新的。”()