gpt4 book ai didi

java - 在这种情况下永远不会抛出这个 AssertionError 吗?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:48:23 26 4
gpt4 key购买 nike

首先是代码,来自 JCIP list http://jcip.net/listings/StuffIntoPublic.javahttp://jcip.net/listings/Holder.java

public class SafePublication {
public static void main(String[] args) throws InterruptedException {
// System.out.println(Thread.currentThread().getName());
StuffIntoPublic t = new StuffIntoPublic();
t.initialize();
while (true) {
new Thread(() -> { t.holder.assertSanity(); }).start();
}
}
}

//@author Brian Goetz and Tim Peierls
class StuffIntoPublic {
public Holder holder;

public void initialize() {
// System.out.println(Thread.currentThread().getName());
holder = new Holder(42);
}
}

//@author Brian Goetz and Tim Peierls
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.");
}
}
}

我是说在这种情况下永远不会抛出 AssertionError,因为 Thread.start() 发生在保证之前。注释的两个 System.out.printlns 都打印 main,这意味着主线程是通过在 while(true) 循环中的线程上创建和调用 start 来生成所有后续线程。

由于这是创建和初始化 Holder 的线程,因此由于发生前保证,所有后续线程都可以安全地成为完全可见的持有者。我说得对吗?

我什至尝试运行这段代码很长时间,但没有断言错误。

但是,如果 main 如下所示,那么我相信有可能出现 AssertionError

 public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName());
StuffIntoPublic t = new StuffIntoPublic();
new Thread(() -> t.initialize() ).start();
while (true) {
new Thread(() -> { t.holder.assertSanity(); }).start();
}
}

最佳答案

是的,这是安全的,因为 Thread#start 保证 happens-before。更罗嗦一点:在 Thread#start 之前发生的任何对任何变量的读/写(如果你愿意,我倾向于按程序顺序考虑 above),也会发生 < em>在该线程中的任何操作之前(它是run 方法)。

事实上,如果之前没有发生(允许重新排序)并且程序执行允许这些潜在的重新排序,那可能会发生中断并抛出该错误。我什至倾向于说 与弱内存模型一起使用的适当 CPU(假设您使用的是 Intel,这是一种强内存模型)可能会增加这种机会,但我不确定。

因此,据我所知,操作将按以下顺序进行:首先,发布引用用变量 n 重新排序(没有 happens-before,所以这是允许的)。 Thread1 创建了一个 Holder 的实例。 Thread2 看到已发布的引用并调用该方法。它读取变量 n0(记住重新排序发生并且 n 尚未写入,因此默认值为 zero),所以它会执行 != 检查,但是 Thread1 创建了 Holder,写入 n 12 例如 before Thread2 再次读取它(在 !=n 部分)。所以这可能会失败。

将值设置为 final 可以解决这个问题,因为它引入了正确的内存屏障,或者 happens-before 规则。

关于java - 在这种情况下永远不会抛出这个 AssertionError 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48138107/

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