从Java并发实践中的书:
要安全地发布对象,两者都要
引用对象和
必须使对象的状态可见
其他线程同时。一个
正确构造的对象可以
安全发布者:
我的问题是:
- 子弹点2和3之间有什么区别?我对两者之间的区别感兴趣
volatile
方法和 final
在安全发布对象方面的方法。
- 最后一场是什么意思 一个正确构造的对象 在第3点?在开始项目符号之前,作者已经提到过他们正在谈论一个正确构造的对象(我假设它不会让它出现
this
参考逃跑)。但他们为什么再次提到正确构造的物体呢?
子弹点2和3之间有什么区别?
volatile
基本上意味着对该字段的任何写入都将从其他线程中可见。因此,当您将字段声明为volatile时: private volatile SomeType field;
,如果构造函数写入该字段,则可以保证: field = new SomeType();
,这个赋值将被随后尝试读取的其他线程可见 field
。
final
具有非常相似的语义:如果您有最终字段,则可以保证: private final SomeType field;
写入该字段(在声明或构造函数中): field = new SomeType();
将不会被重新编码,并且其他线程将可见 如果对象被正确发布 (即没有逃脱 this
例如)。
显然,主要不同的是,如果该字段是最终的,您只能分配一次。
在第3点中,正确构造的物体的最终场是什么意思?
例如,如果你让 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();
}
}
子弹点2和3之间有什么区别?
volatile
基本上意味着对该字段的任何写入都将从其他线程中可见。因此,当您将字段声明为volatile时: private volatile SomeType field;
,如果构造函数写入该字段,则可以保证: field = new SomeType();
,这个赋值将被随后尝试读取的其他线程可见 field
。
final
具有非常相似的语义:如果您有最终字段,则可以保证: private final SomeType field;
写入该字段(在声明或构造函数中): field = new SomeType();
将不会被重新编码,并且其他线程将可见 如果对象被正确发布 (即没有逃脱 this
例如)。
显然,主要不同的是,如果该字段是最终的,您只能分配一次。
在第3点中,正确构造的物体的最终场是什么意思?
例如,如果你让 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
VS final
, 除了那个 final
只能在构造函数中设置一次,因此您阅读的内容永远不会改变。
我相信一个 正确构造的对象 确实是你所指的,一个对象 this
引用没有转义它的构造函数,并以安全的方式发布到它所使用的线程。