[英]final vs volatile guaranntee w.rt to safe publication of objects
From the book Java concurrency in practice :来自 Java concurrency in practice 一书:
To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time.要安全地发布对象,必须同时使对对象的引用和对象的状态对其他线程可见。 A properly constructed object can be safely published by:正确构造的对象可以通过以下方式安全地发布:
Initializing an object reference from a static initializer从静态初始化器初始化对象引用
Storing a reference to it into a volatile field or AtomicReference将对其的引用存储到 volatile 字段或 AtomicReference
Storing a reference to it into a final field of a properly constructed object将对其的引用存储到正确构造的对象的最终字段中
Storing a reference to it into a field that is properly guarded by a将对其的引用存储到由 a 适当保护的字段中
lock.锁。
My questions are :我的问题是:
volatile
approach and final
approach in terms of safe publication of the object .我对volatile
方法和final
方法在对象的安全发布方面的区别很感兴趣。this
reference to escape ).在开始要点之前,作者已经提到他们正在谈论一个正确构造的对象(我认为它不会让this
引用转义)。 But once again why did they mention about properly constructed objects ?但是为什么他们再次提到正确构造的对象?What are the the differences between bullet points 2 and 3 ?要点 2 和要点 3 之间有什么区别?
volatile
basically means that any writes to that field will be visible from other threads. volatile
基本上意味着对该字段的任何写入都将从其他线程可见。 So when you declare a field as volatile: private volatile SomeType field;
因此,当您将字段声明为 volatile 时: private volatile SomeType field;
, you are guaranteed that if the constructor writes to that field: field = new SomeType();
,您可以保证,如果构造函数写入该字段: field = new SomeType();
, this assignment will be visible by other threads that subsequently try to read field
. ,此分配将由随后尝试读取field
其他线程可见。final
has quite similar semantics: you have the guarantee that if you have a final field: private final SomeType field;
final
有非常相似的语义:如果你有一个 final 字段,你可以保证: private final SomeType field;
the write to that field (either in the declaration or in the constructor): field = new SomeType();
写入该字段(在声明或构造函数中): field = new SomeType();
won't be reodered and will be visible by other threads if the object is properly published (ie no escape of this
for example).不会reodered并会被其他线程可见,如果对象是正确发布(即没有逃逸this
为例)。Obviously, the main different is that if the field is final, you can only assign it once.显然,主要的不同在于,如果该字段是最终的,则只能分配一次。
What does he mean by final field of a properly constructed object in point 3 ?第 3 点中正确构造的对象的最终字段是什么意思?
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).例如,如果您让this
从构造函数中逃脱,则最终语义提供的保证就消失了:观察线程可能会看到该字段及其默认值(对于 Object 为 null)。 If the object is properly constructed this can't happen.如果对象构造正确,则不会发生这种情况。
Contrived example:人为的例子:
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();
}
}
There is no difference in what the effects of publishing volatile
vs final
, except that final
can only be set once in the constructor, and thus what you read should never change.发布volatile
和final
的效果没有区别,除了final
只能在构造函数中设置一次,因此您阅读的内容永远不会改变。
I believe a properly constructed object is indeed what you refer to, an object whose this
reference did not escape its constructor and has been published in a safe manner to the thread that it is used in.我相信一个正确构造的对象确实是你所指的对象,一个对象的this
引用没有逃脱它的构造函数,并且已经以安全的方式发布到使用它的线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.