java - Thread什么时候从主内存而不是工作内存中读取非 volatile 变量?

标签 java jvm visibility

public class Main {

public static void main(String[] args) throws InterruptedException {
    Worker w = new Worker();
    w.start();

    sleepQuietly(1000);

    w.alive = false;
    w.join();
}

static class Worker extends Thread {
    boolean alive = true;

    @Override
    public void run() {
        while (alive) {
        }
    }
}

static void sleepQuietly(long millis) {
    try {
        Thread.sleep(millis);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

如果我运行上面的main方法,主线程不会停止。但是如果我运行下面的main方法,main方法就会停止。

public class Main {

public static void main(String[] args) throws InterruptedException {
    Worker w = new Worker();
    w.start();

    sleepQuietly(1000);

    w.alive = false;
    w.join();
}

static class Worker extends Thread {
    boolean alive = true;

    @Override
    public void run() {
        while (alive) {
            sleepQuietly(1); 
        }
    }
}

static void sleepQuietly(long millis) {
    try {
        Thread.sleep(millis);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

“内存模型保证,鉴于上述操作的最终发生,一个线程对特定字段所做的特定更新最终将对另一个线程可见。但最终可以是任意长的时间。长长的代码在不使用同步的线程中,在字段值方面可能会与其他线程完全不同步。特别是,编写循环等待其他线程写入的值总是错误的,除非字段是易变的或通过同步访问“

我在 http://gee.cs.oswego.edu/dl/cpj/jmm.html 中阅读了上面的内容,这是我的问题: 1. 在第一个例子中,为什么工作线程看不到主线程更新的值,因为 JMM 保证一个线程对特定字段的特定更新最终对另一个线程可见

  1. 为什么 Thread.sleep() 会有所不同?

最佳答案

JMM guarantees that a particular update to a particular field made by one thread will eventually be visible to another

它仅在特定条件下保证(最终)可见性。您所指的链接明确说明了这一点。写入非 volatile 字段不属于此类条件。

Why does Thread.sleep() makes difference?

Thread.sleep() 是一种未被 JIT 内联的 native 方法。调用此方法会中断 loop invariant hosting优化,以便每次迭代都重新读取对象字段。但是,此行为是特定 JVM 的实现细节。不保证该程序在其他版本的 JVM 上的行为方式相同。此外,JLS 显式 warns Thread.sleepThread.yield 都没有任何同步语义。

关于java - Thread什么时候从主内存而不是工作内存中读取非 volatile 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49852117/

相关文章:

java - 继承 - 在子类中使用 super.equals() 覆盖父类(super class) equals 中使用的方法

java - Struts2 - 将重定向设置为 false

java - 当文件是参数时无法删除它

java - 如果系统上的物理内存非常低,java 进程会发生什么

java - java IO 中的缓冲区如何工作?

java - 如何控制Java中变量的可见性?

Java Scanner 从字符串中获取数字

javascript - 如何使用 jQuery 隐藏 HTML 列表并增加以下输入?

c# - 将图片显示为隐藏或可见

java - GWT编译器: Error: Could not create the Java Virtual Machine