线程在让出时间片的时候会将自己修改的主内存的值刷新回主内存吗?

线程在让出时间片的时候会将自己修改的主内存的值刷新回主内存吗?

3个回答

首先:不一定会将自己修改的主内存的值刷新回主内存
然后:楼上实例有问题
执行了System.out.println(),我们看源码就知道 println中是有syn锁的
锁释放、获取的时候会把当前线程的共享变量刷新到主内存
如果,两个线程循环调用,不输出,你就会发现,服务跑一会儿就会处于一直等待中
所以,楼上的实例不对

这种模棱两可的问题还是需要看官方文档:楼主可以参照 https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html
17.3. Sleep and Yield 中的描述

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.

事实是,编译器在调用sleep方法前,不一定会去刷新主内存。sleep结束后,也不一定会去reload.

其实与其说是线程主动将数据刷新到主内存,不如说是在 Java 内存模型的约束下对主内存数据的读取是遵循 happen-before 规则约束的。
如果一个线程休眠之前修改了一个共享变量的值,然后休眠了,而另一个线程要去读该值,那么根据 happen-before 原则,它读取之前必须先执行写操作,就是题中理解的刷新到主内存。
写了一个测试 demo :

import java.util.Date;

public class TestThread {

    public static int count = 0;

    public static void main(String[] args) {
        new Thread(()-> {
            try {
                Thread.sleep(500);
                System.out.println(new Date()+Thread.currentThread().getName()+","+count);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }).start();

        try {
            count = 10;
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+","+count);

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

是能够读取到最新的值的,可以搜下 JMM 相关的知识补充验证一下。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问