gpt4 book ai didi

java - 同步如何有助于变量可见性?

转载 作者:行者123 更新时间:2023-12-01 14:26:07 25 4
gpt4 key购买 nike

public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}

public static void main(String[] args) {
new ReaderThread().start();
number = 42;
ready = true;
}
}

根据“Java Concurrency in Practice”,它可能会打印 0,因为在写入数字之前,写入就绪可能对读取器线程可见,或者程序根本不会终止,因为它没有使用足够的资源同步。不保证主线程写入的就绪值和数量对读取器线程可见。

这怎么可能?程序将由线程顺序运行,它首先写入数字,然后写入就绪变量。不是吗?这个程序怎么可能永远循环下去?

最佳答案

无法保证通过更改一个线程中的变量,其他线程将看到这些更改的结果。从技术上讲,它们之间没有发生之前的关系,因此没有保证(尽管在实践中您几乎总是会看到更改)。

这就是线程可能永远运行的原因。

其次,为什么有时是 0 ?

好吧JLS说的是

Writes in one thread that are in a data race with reads in another thread may, for example, appear to occur out of order to those reads.

这意味着你的

number = 42;
ready = true;

可以按任何顺序发生。现在它们更有可能按顺序出现,但同样不能保证。

您可以通过将变量更改为 volatile 来修复此问题,在这种情况下,读者始终可以看到写入内容,或者将您突变的代码设置为关键部分(请参阅本书)。一般来说,我觉得使用太多的 volatile 变量有点麻烦,所以你应该尝试谨慎使用它们,例如线程“运行”变量。

public class NoVisibility {
private static volatile boolean ready;
private static volatile int number;

private static class ReaderThread extends Thread {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}

public static void main(String[] args) {
new ReaderThread().start();
number = 42;
ready = true;
}
}

关于java - 同步如何有助于变量可见性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17165212/

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