Thread.sleep结束时会刷新工作内存吗

如题在学习可见性时写了如下代码:

    public static boolean flag = false;

    @Test
    public void start() throws InterruptedException {

        Thread read = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (flag) {
                    System.out.println("yes");
                } else {
                    System.out.println("no");
                }
            }
        });
        read.start();

        Thread write = new Thread(new Runnable() {
            @Override
            public void run() {
                flag = true;
            }
        });
        write.start();

        Thread.sleep(2000);
    }

控制台输出:yes
请问这是因为Thread.sleep会刷新工作内存吗?

阅读 3.6k
3 个回答

你这样的写法我们可以看到,在read线程内部先暂停了1s,然后在获取flag进行比较,但是这样的话会出现一个问题,write线程已经完全操作完了并且把flag修改了,此时你再获取flag那就已经是最新的了,所以会是true!所谓的线程之间不可见是因为线程内部保有了自己的副本,但是read线程在获取flag并且创建自己的副本的时候已经是最新的了,所以建议这样修改

public static boolean flag = false;

    public void start() {

        Thread read = new Thread(() -> {
            while (!flag) {
                
            }
        });
        read.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread write = new Thread(() -> flag = true);
        write.start();
    }

sleep只是暂停当前线程一定时间,让cpu的高速缓存与内存接下来的若干时钟周期内进行同步(仅是可能,不能完全保证及时),因此或许能读到最新改的值。

如果要保证内存可见性,还是用synchronizedvolatile吧。

新手上路,请多包涵
public class MainOther {

    private static  int a =1;

    public static void main(String[] args) throws InterruptedException {

        new Thread(() -> {

            while (a==1){

                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            System.out.println("end");

        }).start();

        TimeUnit.SECONDS.sleep(1);
        a=2;
    }


}

是的 ,把 sleep去掉 程序就一直运行
虽然jvm没说,但确实是会去同步

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题