gpt4 book ai didi

java - 为什么发布最终字段是安全的?

转载 作者:行者123 更新时间:2023-12-01 09:22:05 27 4
gpt4 key购买 nike

我正在阅读 Java Concurrency in Practice by Brian Goetz .在第 51 页。在其中一个脚注中,他说:

While it may seem that field values set in a constructor are the first values written to those fields and therefore that there are no “older” values to see as stale values, the Object constructor first writes the default values to all fields before subclass constructors run. It is therefore possible to see the default value for a field as a stale value.

所以,final 字段的概念现在对我来说还不是很清楚。考虑示例类:

public class MyClass{
private final MyImmutableClass mic;

public MyClass(){
mic = MyImmutableClass.empty();
}
}

根据上面的脚注,mic 字段被分配了两次,一次是由 Object 的构造函数和一次由 MyClass 的构造函数本身。现在,假设我们不安全地发布了一个 MyClass 对象(例如通过 public 字段):

public final MyClass mc;

谁保证 mc 总是被处于一致状态的任何线程观察到?为什么某些线程不能意外观察到默认值?

据我所知,final 字段本身只保证对象构造后不能分配引用。如果我们将 mc 声明为 volatile,那就很清楚了。任何读取该字段的线程都应该直接从内存中读取它。禁止从缓存中读取。

UPD:发布示例:

public static void main(String[] args){
class MyRunnable implements Runnable(){
private SomeClass sc;
public MyRunnable(SomeClass sc){
this.sc = sc;
}
public void run(){
//do some with sc
}
}
SomeClass sc = getInitialized();
ExecutorService es = Executors.newFixedThreadPool(10);
MyRunnable mr = new MyRunnable(sc);
//submiting mr to es 10 times
es.awaitTemination();
es.shutdown();
}

private static SomeClass getInitialized(){
SomeClass sc = new SomeClass();
sc. initialize();
return sc;
}
public class SomeClass
public MyClass mc;

public void initialize(){
mc = new MyClass();
}
}

SomeClass 实例将跨多个线程发布。某些线程是否可以观察到 mic 字段的默认值?

最佳答案

mc 在你的例子中是一个实例变量。这意味着您必须具有包含 mc 的类的完全初始化实例,以便访问某个实例的 mc 的任何代码都不会抛出 NullPointerException。所以mc肯定会在访问的时候被初始化。

关于java - 为什么发布最终字段是安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34489288/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com