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 保证一个线程对特定字段的特定更新最终对另一个线程可见
- 为什么 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.sleep
和 Thread.yield
都没有任何同步语义。
关于java - Thread什么时候从主内存而不是工作内存中读取非 volatile 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49852117/