[英]When does Thread read a non-volatile variable from main memory instead of working memory?
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();
}
}
}
If I run the main method above, the main thread won't stop.But if I run the main method below, the main method will stop. 如果运行上面的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();
}
}
}
"The memory model guarantees that, given the eventual occurrence of the above operations, a particular update to a particular field made by one thread will eventually be visible to another. But eventually can be an arbitrarily long time. Long stretches of code in threads that use no synchronization can be hopelessly out of synch with other threads with respect to values of fields. In particular, it is always wrong to write loops waiting for values written by other threads unless the fields are volatile or accessed via synchronization" “内存模型保证,鉴于上述操作的最终发生,一个线程对特定字段的特定更新最终将对另一线程可见。但是最终可能是任意长时间。线程中的长段代码会在字段值方面,不使用任何同步都可能与其他线程不同步。特别是,除非这些字段是易失的或通过同步访问,否则编写循环等待其他线程写入的值总是错误的。”
I read above in http://gee.cs.oswego.edu/dl/cpj/jmm.html , and here is my question: 1. In the first example, why worker thread can't see the value updated by main thread as the JMM guarantees that a particular update to a particular field made by one thread will eventually be visible to another 我在上面的http://gee.cs.oswego.edu/dl/cpj/jmm.html中阅读了以下内容,这是我的问题:1.在第一个示例中,为什么工作线程看不到主线程更新的值因为JMM保证一个线程对特定字段的特定更新最终将对另一个线程可见
JMM guarantees that a particular update to a particular field made by one thread will eventually be visible to another JMM保证一个线程对特定字段所做的特定更新最终将对另一个线程可见
It guarantees (eventual) visibility only under certain conditions. 它仅在某些条件下保证(最终)可见性。 The link you are referring to explicitly says that. 您所指的链接明确表示。 A write to a non-volatile field is not among such conditions. 对非易失性字段的写操作不在这种条件之内。
Why does Thread.sleep() makes difference? 为什么Thread.sleep()有所作为?
Thread.sleep()
is a native method that is not inlined by JIT. Thread.sleep()
是JIT未内联的本机方法。 Calling this method breaks loop invariant hosting optimizations, so that object field is re-read each iteration. 调用此方法将破坏循环不变的托管优化,以便在每次迭代时重新读取对象字段。 However, this behavior is an implementation detail of the particular JVM. 但是,此行为是特定JVM的实现细节。 It is not guaranteed that the program will behave the same way on other versions of JVM. 不保证该程序在其他版本的JVM上的行为也相同。 Moreover, JLS explicitly warns that neither Thread.sleep
nor Thread.yield
have any synchronization semantics. 此外,JLS明确警告 Thread.sleep
和Thread.yield
具有任何同步语义。
Take a look at: https://help.semmle.com/wiki/display/JAVA/Spin+on+field 看看: https : //help.semmle.com/wiki/display/JAVA/Spin+on+field
class Spin {
public boolean done = false;
public void spin() {
while(!done){
}
}
}
class Spin { // optimized
public boolean done = false;
public void spin() {
boolean cond = done;
while(!cond){
}
}
}
The method repeats the while-loop until the value of the field done is set by another thread. 该方法重复while循环,直到完成的字段的值由另一个线程设置。 However, the compiler could optimize the code as shown in the second code snippet, because the field done is not marked as volatile and there are no statements in the body of the loop that could change the value of done. 但是,编译器可以优化代码,如第二代码段所示,因为未完成字段未标记为volatile,并且循环主体中没有任何语句可以更改done的值。 The optimized version of spin loops forever, even when another thread would set done to true. 即使另一个线程将done设置为true,自旋循环的优化版本也会永远存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.