gpt4 book ai didi

java - 能见度保证

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:12:52 26 4
gpt4 key购买 nike

我已经阅读了 JCIP 对 16.3 节“初始化安全” 的一些解释,但仍然不清楚。该部分指出

“此外,任何可以通过正确构造的对象的 final 字段访问的变量(例如 final 数组的元素或 final 字段引用的 HashMap 的内容)也保证是对其他线程可见。”

所以如果我有以下可变对象:

public final class Container{
private String name;
private int cupsWon;
private double netWorth;

public Container( String name, int cupsWon, double netWorth ){
this.name = name;
this.cupsWon = cupsWon;
this.netWorth = netWorth;
}

//NO Setters
//Getters
}

然后,Thread 1 如下创建它并将 c 传递给 Thread2

final Container c = new Container("Ted Dibiasi", 10, 1000000);

Thread2(不是并发,假设在 1 毫秒后),读取 c 的值,Thread2 是否有可能看到

c.name=null or
c.cupswon=0 or worst of all,
c.netWorth=0.0?

干杯

更新

我注意到对于具有 getter 的类存在一些混淆。我正在更新源代码,希望这会很清楚。感谢大家的观看。

public final class Container{

private String name;
private int cupsWon;
private double netWorth;

public Container( String name, int cupsWon, double netWorth ){
this.name = name;
this.cupsWon = cupsWon;
this.netWorth = netWorth;
}

public final String getName(){
return name;
}

public final int getCupsWon(){
return cupsWon;
}

public final double getNetWorth(){
return netWorth;
}

}

//------------

public final class Producer{

private final Client client;

public Producer( Client client ){
this.client = client;
}

//Thread1 call produce()
public final void produce( ){
final Container c = new Container("Ted Dibiasi", 10, 1000000);
client.update( c );
}

}

//----

public final class Client{

private Container c;
//private volatile Container c;

public final void update( Container c ){
this.c = c;
}

//Thread2 calls consume().
public final void consume( ){
String name = c.getName();
int cupsWon = c.getCupsWon();
double netWorth = c.getNetWorth();
}

}

我的问题是:

a) 当 Thread2 调用 consume() 时,name、cupsWon、netWorth 是否可以为 null、0 或 0.0?我的想法是它可以,因为容器类中的字段不是最终的,所以没有可见性保证。

b) 但是,然后我阅读了第 16.3 节和有关“可以通过正确构造的对象的最终字段访问的变量”的内容,这是否意味着因为 Container c 的实例被声明为 final,我们确实在 consume() 中有可见性保证?

final Container c = new Container("Ted Dibiasi", 10, 1000000);

c) 在 Client 类中将对 Container 的引用声明为 volatile 不会解决与引用相关的字段的可见性问题。

最佳答案

final Container c = new Container("Ted Dibiasi", 10, 1000000);

如果 cThread1 中的最后一个字段而不是局部变量,那么引用 Java Language Specification适用于此最终字段 c:

An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

The usage model for final fields is a simple one: Set the final fields for an object in that object's constructor; and do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields. It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.

虽然这里的措辞含糊,但我认为“正确初始化的值”和“最新的作为最终字段”意味着如果你通过cThread1 构造函数之外的 Thread2Thread2 将始终看到一个完整构造的 Container 其字段已初始化的实例。

关于java - 能见度保证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32464456/

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