gpt4 book ai didi

java - 为什么子线程看不到改变后的静态变量? JMM 或 volatile

转载 作者:行者123 更新时间:2023-12-01 16:46:38 25 4
gpt4 key购买 nike

以下是 volatile 关键字的使用示例。

public class Test3{
public static volatile boolean stop = false;// if volatile is not set, the loop will not stop
public static void main(String[] args) throws InterruptedException{
Thread thread = new Thread(){
public void run() {
int i=0;
while(!stop){
i++;
// add this line
// System.out.println(i);
// or this block
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
}
};
thread.start();
Thread.sleep(2000);
stop = true;
}
}

很容易理解,如果设置了 volatile,JVM 应该在检查其值的同时从内存加载更新后的值,然后 while 循环可以按预期停止。但问题是,静态变量不应该同时改变吗?可能会有一些延迟,但最终应该检测到这种变化。不?我测试过,如果我们添加一些打印代码或 sleep 代码,可以检测到这种变化吗?有人可以教我为什么这么喜欢吗?也许与 JMM 有关。

最佳答案

时间,从挂钟时间的意义上来说,对于内存可见性没有任何意义。重要的是同步操作之间的同步顺序。读取和写入非 volatile 字段不是同步操作,因此在没有任何其他同步操作的情况下,它们之间没有顺序。

所以即使主线程在一年前完成,那么从主线程的角度来看,写入肯定已经完成,子线程可能会继续运行,永远运行;从它的角度来看,写入并没有发生。它也不知道主线程已经终止。请注意,执行能够检测到其他线程已终止的操作是可以建立顺序的同步操作。

但由于实际的程序行为还取决于 JIT 编译器和优化器,因此某些代码更改可能会产生影响,即使不能保证。

例如插入 sleep 并不意味着任何内存可见性:

JLS §17.3. Sleep and Yield :

It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call to Thread.sleep or Thread.yield, nor does the compiler have to reload values cached in registers after a call to Thread.sleep or Thread.yield.

但它可能会阻止优化器将循环视为需要优化的热点。

当您插入 System.out.println 语句时,PrintStream 的内部同步可能会对整体内存可见性产生影响,尽管这种影响也并不明显。不能保证,因为主线程不会在该 PrintStream 上同步。

顺便说一句,甚至不能保证相同优先级的线程之间会发生抢占式线程切换。因此,如果 JVM 在调用 start() 之后尝试完成子线程,然后将 CPU 返回给主线程,那么这将是一次有效的执行。

在该执行场景中,循环中没有 sleep ,子线程永远不会放弃 CPU,因此 stop 永远不会设置为 true,即使声明为 volatile 。这将是避免轮询循环的另一个原因,尽管现实生活中可能不存在没有抢占式线程切换的执行环境。当今的大多数执行环境甚至都有多个 CPU,因此不放弃 CPU 不会阻止其他线程执行。

不过,为了形式上正确,您应该在写入 stop 变量和读取变量之间强制执行顺序,例如声明变量 volatile 并插入当 quit 仍为 false 时,可能会导致线程最终释放 CPU 的操作。

关于java - 为什么子线程看不到改变后的静态变量? JMM 或 volatile ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49384377/

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