synchronized如何实现可见性的?

问题描述

synchronized是如何实现可见性的,我在线程B加入了一个空的同步代码块后,线程B就能正确读到i的值为1,实现了可见性,如果不加同步代码块线程B就不会停止。可是就算加了一个空的同步代码块,线程A执行i=1后应该也只是在工作内存中执行的,并未刷新到主存,虽然线程B执行同步代码块加锁后会从主存中读取,但我认为此时线程A还未把i=1从工作内存中刷新到主存吧,为什么这个同步代码块可以实现i的可见性。

相关代码

public class b {

public static int i;
public static void main(String[] args) throws Exception {
    Object o = new Object();
    new Thread(() -> {             //线程A
        try {
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        i = 1;
        while (true) {
        }
    }).start();
    new Thread(() -> {            //线程B
        while (true) {
            synchronized (o) {   //加了这个同步代码块后线程B就能马上停止,里面什么都不写
            }
            if (i == 1) {
                System.out.println("结束");
                break;
            }
        }
    }).start();
}

}

题目描述

题目来源及自己的思路

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 3.8k
1 个回答

首先在定义上:JMM关于synchronized的两条语义规定:
线程解锁前,必须把共享变量的最新之刷新到主内存中
线程加锁前,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值

在实现上:无论是锁还是volatile的可见性都是通过内存屏障(Memnory Barrier)来实现的

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