【发布时间】:2016-08-07 10:39:31
【问题描述】:
来自 Java Concurrency In Practice-的抽象/sn-p-
// Unsafe publication
public Holder holder;
public void initialize(){
holder = new holder(42);
}
不正确发布的对象可能会出现两件事。其他 线程可能会看到持有者字段的陈旧值,因此会看到 null 引用或其他较旧的值,即使某个值已被 放置在支架中。但更糟糕的是,其他线程可能会看到 最新的 持有者参考的值,但状态的陈旧值 持有人。为了使事情变得更难预测,线程可能会看到 第一次读取字段时的陈旧值,然后是更新的 下一次的值,这就是 为什么 assertSanity 可以抛出 断言错误。
对象引用对另一个线程可见并不一定意味着该对象的状态对消费线程可见
public class Holder{
private int n;
public Holder(int n) {
this.n = n;
}
public void assertSanity(){
if (n != n)
throw new AssertionError("This statement is false.");
}
}
当然,解决它的方法之一是做/制作
public volatile Holder holder;
作者提出了不同的方法-
如果 Holder 是不可变的,assertSanity 就不能抛出 AssertionError,即使 Holder 没有正确发布。)
public class Holder{
private final int n;
//...
}
但是怎么做呢?不安全的出版物仍然存在。我认为线程仍然有可能在持有人上获得 null 引用。请提出建议。
【问题讨论】:
标签: java multithreading concurrency java.util.concurrent