volatile保证可见性

首先,每个线程都有自己的工作内存(每个线程私有),而执行任务时,要先从主内存(公共部分)读取要操作的变量,拷贝到自己的工作内存当中,然后对变量进行操作,操作完成后要将变量重新写入主内存当中。

我们可以看到每个线程操作变量的执行流程大概是上图所示的样子

那么我们来进行代码实践:


class MyData{

    int number = 0;

    public void addT060(){
        this.number = 60;
    }

}


/**
 * 1.验证volatile的可见性
 *   1.1 假如int number =0; number变量之前根本没有添加volatile关键字修饰,没有可见性
 */
public class VolatileDemo {

    public static void main(String[] args) { //main是一切方法的运行入口
        MyData myData = new MyData(); //资源类

        new Thread(()->{
            System.out.println(Thread.currentThread().getName() + "\t come in");
            //暂停一会儿线程
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myData.addT060();
            System.out.println(Thread.currentThread().getName() + "\t updated number value" + myData.number);
        },"AAA").start();

        //第二个线程就是我们的main线程
        while (myData.number == 0){
            //main线程就一直在这里等待循环,直到number值不再等于零
        }
        System.out.println(Thread.currentThread().getName() + "\t mission is over,main get number value:"+myData.number);
    }

}

如果没有加volatile进行修饰变量那么main线程会一直处于等待状态如下图:

 

 而加了volatile后的代码:

class MyData{

    volatile int number = 0;

    public void addT060(){
        this.number = 60;
    }

}


/**
 * 1.验证volatile的可见性
 *   1.1 假如int number =0; number变量之前根本没有添加volatile关键字修饰,没有可见性
 */
public class VolatileDemo {

    public static void main(String[] args) { //main是一切方法的运行入口
        MyData myData = new MyData(); //资源类

        new Thread(()->{
            System.out.println(Thread.currentThread().getName() + "\t come in");
            //暂停一会儿线程
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myData.addT060();
            System.out.println(Thread.currentThread().getName() + "\t updated number value" + myData.number);
        },"AAA").start();

        //第二个线程就是我们的main线程
        while (myData.number == 0){
            //main线程就一直在这里等待循环,直到number值不再等于零
        }
        System.out.println(Thread.currentThread().getName() + "\t mission is over,main get number value:"+myData.number);
    }

}

在此处我们可以查看以下输出结果:

结论:上图我们看到两个线程读取完数据后,没加volatile时,线程AAA将数据写回主内存区域后,main线程看不到变量number的变化,于是会一直处于循环状态,但加了volatile关键字修饰后,则线程AAA修改number变量后会通知其他线程可见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值