简体   繁体   English

最终与 volatile 保证对象的安全发布

[英]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 :我的问题是:

  1. What are the the differences between bullet points 2 and 3 ?要点 2 和要点 3 之间有什么区别? I am interested in the difference between volatile approach and final approach in terms of safe publication of the object .我对volatile方法和final方法在对象的安全发布方面的区别很感兴趣。
  2. What does he mean by final field of a properly constructed object in point 3 ?第 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 ).在开始要点之前,作者已经提到他们正在谈论一个正确构造的对象(我认为它不会让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.发布volatilefinal的效果没有区别,除了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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM