简体   繁体   English

线程何时从主内存而不是工作内存中读取非易失性变量?

[英]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保证一个线程对特定字段的特定更新最终将对另一个线程可见

  1. Why does Thread.sleep() makes difference? 为什么Thread.sleep()有所作为?

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.sleepThread.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.

相关问题 非易失性字段何时写入主存储器 - When is non-volatile field write to main memory 如果直接从内存中读取易失性字段,那么从哪里读取非易失性字段? - If volatile fields are read directly from memory, where are non-volatile fields read from? AtomicInteger没有从主存储器中读取非易失性可变参考值 - AtomicInteger not reading value from main memory for non-volatile mutable refrence 在从另一个线程读取期间是否可以读取非易失性变量的陈旧值? - Is it possible to read stale value of non-volatile variable during read from another thread? compareAndSwap 一个普通成员(非易失性成员)仍然具有易失性读写的内存语义 - compareAndSwap a common member ( non-volatile member ) still has memory semantics of volatile read and write 非易失性变量是否需要同步? - Does a non-volatile variable need synchronized? 同步保证线程是否会看到另一个线程修改的非易失性变量的最新值? - Does synchronized guarantee a thread will see the latest value of a non-volatile variable being modified by another thread? 由该类的方法延迟分配的非易失性变量不能被另一个线程读取吗? - Can a non-volatile variable that is delayed assigned to by a method of the class not be read by another thread? 为什么对非易失性的写入对主线程可见? - Why is the write to non-volatile visible to the main-thread? java,什么时候(以及多长时间)线程可以缓存非易失性变量的值? - java, when (and for how long) can a thread cache the value of a non-volatile variable?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM