【问题标题】:Why final key word can guarantee safe publication if constructor is not synchronized?如果构造函数不同步,为什么final关键字可以保证安全发布?
【发布时间】:2017-03-28 07:47:14
【问题描述】:

Java Concurrency in Practice一书提到

正确构造的对象可以通过以下方式安全发布:

Storing a reference to it into a final field of a properly constructed object

首先,我认为是因为 final 字段只能在类构造函数中初始化,而 Java 构造函数是隐式“Synchronized”。然而,我意识到事实并非如此。

class Student{
   int student_id;
   public Student(int i){
       student_id = i;
   }
}

class Test {
   private final Student student;
   public Test(){
         student = new Student(1);
         ...
   }
}

比如上面的代码,JVM如何保证student是一个安全的出版物?

静态决赛怎么样?

class Test {
       private static final Student student;
       public Test(){
             student = new Student(1); //will this be partially constructed when the other thread reads a bad object ?

             ...
       }
    }

final 本身是否暗示了一些东西,以便 Jave Memory Model 将保证相同的发布?

【问题讨论】:

  • 你最后的 sn-p 不会编译。
  • 是的,我刚刚意识到静态最终文件必须在类加载时初始化,而不是在创建新实例时初始化。

标签: java multithreading thread-safety


【解决方案1】:

JVM 保证学生是安全的出版物?

有多种方法可以确保安全发布,通常使用写屏障就足够了。在任何情况下,JVM 都必须为其运行的处理器保证这一点。

静态决赛怎么样?

所有静态字段都以单线程方式初始化。无论你是否使用 final,类初始化都是线程安全的。

final 本身是否暗示了一些东西,因此 Jave Memory Model 将保证相同的发布?

除了构造函数,不是真的。支持安全发布不应更改的值更容易。

【讨论】:

  • 我认为我感到困惑的部分是在构造函数中执行此行 student = new Student(1) 时,是否可能部分构造了 new Student(1) 而另一个线程读取了由于构造函数未同步,因此对象不正确?
  • @GuifanLi 如果字段不是最终的并且对象在线程之间传递而不使用写屏障,则可能会发生这种情况。
  • 那么为什么构造函数中的final可以保证安全发布呢? final 告诉 JMM 什么?
  • @GuifanLi JMM 说他们必须安全发布。这不是其他原因的结果,而是直接要求。请注意,在 Java 5.0 之前它没有这样做。
猜你喜欢
  • 2016-04-02
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多