java - Java 不一致状态比较

标签 java multithreading volatile mutable

Java并发实践中给出了一个示例*来演示可见性的问题,其中两个不同的线程可能看不到up - 由于缺乏同步而导致任何特定可变对象的最新状态。

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.");
        }
    }

在这个特定的示例中,书中指出线程“A”应该首先初始化并通过线程不安全的方式发布它,例如:

public Holder holder;
public void initialize() {
    holder = new Holder(42);
}

然后线程“B”调用holder.assertSanity(),由于状态不一致,完全有可能抛出AssertionError

现在,我理解了该论点的基本前提,其中对可变变量所做的更改可能永远不会被另一个线程观察到。但我在这里感到困惑的是,它正在比较相同的(或者我认为是这样的)引用n!= n

这不是比较可 rebase 元字段private int n的值吗?不管线程 A 的 n 值现在可能为 42,线程 B 的值 0(默认),不应该直接调用来检查它在同一线程中的值 线程一致?即在线程 A 中调用 assertSanity() 将检查是否 42 != 42,而在线程 B 中调用 0 != 0

*引用书中的 3.5 安全发布、列表 3.14 和 3.15。

最佳答案

问题在于,在表达式 n != n 中,变量 n 将被加载两次(假设没有对字节码进行优化)。在这两次加载之间,另一个线程可以更改该值。

关于java - Java 不一致状态比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50656318/

相关文章:

c - C中的 volatile 变量或 volatile 结构问题

java - AtomicInteger 和 volatile

java - 如何在jsp或html5的数据列表中添加复选框

java - 如何匹配以或等于搜索字符串开头的 TreeMap 值

java - 并发 - 循环大型数据集并执行操作

java - volatile 数组的奇怪行为

Java多线程问题.join()

java - 如何在 Spring Restful Webservice 中接受 JSON 输入?

后台 worker 中的 C# ProgressBar 数据绑定(bind)

java - 使用阈值的多线程冒泡