我已经阅读了JCIP第16.3节“初始化安全性”的一些解释,但仍然不清楚.该部分指出
“此外,任何可以通过正确构造的对象的最终字段(例如最终数组的元素或最终字段引用的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
}
然后,线程1按如下方式创建它并将c传递给Thread2.
final Container c = new Container("Ted Dibiasi", 10, 1000000);
Thread2(不是同时,假设在1 ms之后),读取c的值,是否有可能看到Thread2
c.name=null or
c.cupswon=0 or worst of all,
c.netWorth=0.0?
干杯
UPDATE
我注意到有关吸气鬼的课程有些困惑.
我正在更新源代码,希望这将是明确的.
谢谢大家一起来看看.
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?我的想法是它可以因为因为Container类中的字段不是最终的,所以没有可见性保证.
b)然而,然后我阅读了第16.3节和关于“可以通过正确构造的对象的最终字段到达的变量”的位,这是否意味着因为Container c的实例被声明为final,我们确实有可见性保证消耗()?
final Container c = new Container(“Ted Dibiasi”,10,1000000);
c)在Client类中声明对Container的引用为volatile,不会解决与引用相关的字段的可见性问题.