通过案例说明synchronized如何实现多线程下共享变量的不可见问题。

问题描述:

       博主在学习volatile时,看到java语言层面支持的可见性实现方式有以下两种:
1>synchronized
2>volatile

对于synchronized实现可见性的解释是:synchronized会清空线程的工作内存,并从主内存中重新获取变量的值。相信许多人和我一样,看到这个解释的时候都是一脸懵逼的,下面我将通过一个案例说明synchronized如何实现可见性。

多线程下共享变量不可见问题描述(知道的同学可以跳过):

首先需要2个线程,一个主线程,一个自定义线程

自定义线程代码如下:

class MyThread01 extends Thread{
    private boolean flag01 = true;
    @Override
    public void run(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag01 = false;

    }

    public boolean getFlag01(){
        return flag01;
    }

}

自定义线程中有个成员变量flag01,初始默认值为true。自定义线程的run方法睡眠5秒后将flag01的值修改为false。

public static void main(String[] args){
        MyThread01 myThread01 = new MyThread01();
        myThread01.start();

        while(true){
            if (myThread01.getFlag01()){
                System.out.println(111);
            }
        }
    }

主线程先启动自定义线程,然后在死循环中判断flag01的值,若为true则输出111,若为false则不处理。

以上代码运行的结果为:主线程无限输出111,自定义线程5秒后修改flag01的值为flase后依然会继续输出111。

自定义线程修改完共享变量flag01后,主线程不知道,这就是多线程下共享变量不可见问题。这是由于JMM中,每个线程都有自己的工作内存,在从主内存中获取到变量的值后,即使主内存中该变量发生改变,任然会使用工作内存中的值来操作。

synchronized实现可见性:

        一定要在获取共享变量之前执行synchronized语句块,synchronized()的括号中随便放入什么,因为实现可见性与锁的机制无关。自定义线程的成员变量flag01默认值为false,run方法睡眠5秒后将flag01的值改为true,再睡眠5秒后将flag01的值改为false。

public class Test01{

    public static void main(String[] args){
        MyThread01 myThread01 = new MyThread01();
        myThread01.start();
        while(true){
            synchronized (myThread01){
                if (myThread01.getFlag01()){
                    System.out.println(111);
                }
            }
        }
    }
}

class MyThread01 extends Thread{
    private boolean flag01 = false;
    @Override
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag01 = true;
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag01 = false;
    }

    public boolean getFlag01(){
        return flag01;
    }

}

main方法执行结果为:首先什么也不输出(flag01默认为false),5秒后输出111(5秒后run方法修改flag01的值为true),再5秒后什么也不输出(再睡眠5秒后将flag01的值改为false)。

由此可见synchronized实现可见性准确的解释是:synchronized清空了线程的工作内存,当执行到获取共享变量的代码时(getFlag01()方法),会重新从主内存中获取,使得线程工作内存与主内存的值一致。

总结:

        synchronized实现可见性与锁的机制无关,而是由于synchronized会清空线程的工作内存,每次执行到获取共享变量的代码时(执行getFlag01()方法时)都会重新从主内存中获取共享变量,因此获得的是共享变量最新值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值