问题描述
摘自《 Java并发实践》:
From the book Java concurrency in practice :
-
从静态初始化程序初始化对象引用
Initializing an object reference from a static initializer
将对其的引用存储到volatile字段或AtomicReference
Storing a reference to it into a volatile field or AtomicReference
将对其的引用存储到适当构造的最终字段中 对象
Storing a reference to it into a final field of a properly constructed object
将对其的引用存储到由a
适当保护的字段中 锁定.
Storing a reference to it into a field that is properly guarded by a
lock.
我的问题是:
- 要点2和3之间有什么区别?我对
volatile
方法和final
方法之间在对象的安全发布方面的区别感兴趣. - 第3点中正确构造的对象的最终字段 是什么意思?在开始要点之前,作者已经提到他们正在谈论一个正确构造的对象(我认为不会让
this
引用转义).但是他们又为什么提到适当构造的对象?
- What are the the differences between bullet points 2 and 3 ? I am interested in the difference between
volatile
approach andfinal
approach in terms of safe publication of the object . - What does he mean by final field of a properly constructed object in point 3 ? Before starting the bulleted points authors already mentioned that they are talking about a properly constructed object (which I assume is not letting the
this
reference to escape ). But once again why did they mention about properly constructed objects ?
推荐答案
-
volatile
基本上意味着对该字段的任何写入将在其他线程中可见.因此,当您将字段声明为volatile:private volatile SomeType field;
时,可以保证,如果构造函数写入该字段:field = new SomeType();
,则随后尝试读取field
的其他线程将看到此分配. -
final
的语义非常相似:如果有一个final字段,则可以保证:private final SomeType field;
对该字段的写入(无论是在声明中还是在构造函数中):field = new SomeType();
不会被重复如果该对象已正确发布,则其他线程将显示 (例如,this
不能转义). volatile
basically means that any writes to that field will be visible from other threads. So when you declare a field as volatile:private volatile SomeType field;
, you are guaranteed that if the constructor writes to that field:field = new SomeType();
, this assignment will be visible by other threads that subsequently try to readfield
.final
has quite similar semantics: you have the guarantee that if you have a final field:private final SomeType field;
the write to that field (either in the declaration or in the constructor):field = new SomeType();
won't be reodered and will be visible by other threads if the object is properly published (i.e. no escape ofthis
for example).
显然,主要区别在于,如果该字段为final,则只能分配一次.
Obviously, the main different is that if the field is final, you can only assign it once.
例如,如果让this
从构造函数中退出,则最终语义所提供的保证将消失:观察线程可能会看到具有其默认值的字段(对象为null).如果对象构造正确,就不会发生.
If, for example, you let this
escape from the constructor, the guarantee provided by the final semantics is gone: an observing thread might see the field with its default value (null for an Object). If the object is properly constructed this can't happen.
人为的例子:
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();
}
}
这篇关于安全发布对象的最终vs易失性担保的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!