volatile关键字使用

volatle关键字:当多个线程操作共享数据时,可以保证内存中的数据可见。相较于synchronized是一种较为轻量级的同步策略。
注意:
1.volatile 不具备"互斥性"
2.不能保证变量的”原子性“
举例说明volatile作用:

public class TestVolatile {
    public static void main(String[] args) {
    	//创建线程
        ThreadDemo th = new ThreadDemo();
        new Thread(th,"MyThread").start();
        //循环等待,flag == true 时会结束循环
        while (true){
            if(th.isFlag()){
                System.out.println("===============");
                break;
            }
        }

    }
}
//ThreadDemo实现的线程只将flag修改为true
class ThreadDemo implements Runnable{

    private  boolean flag = false;

    public void run() {
        flag = true;
        System.out.println("flag==>"+flag);

    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

以上程序很简单,先创建一个线程,将flag由false修改为true,main方法里面有个while循环,只有flag为true时,才会结束循环。
看一下执行结果:
在这里插入图片描述
在这里插入图片描述
多执行几次会发现出现以上两种结果,第一中程序想入死循环,第二种正常结束。what happend?
因为各个线程为了增加执行速度,都会将会有自己的缓存,先将数据从主存中拷贝过来,修改后在返回给主存。
在这里插入图片描述

注意上面1 ,2,3不代表执行顺序
1代表MyThread线程从主从中得到flag初始值false,2代表线程将falg修改完后同步到主存,3代表main线程得到flag的值。
分析第一种为啥会陷入死循环,不是创建的线程已经将flag修改为true了吗,while()循环里为啥不会跳出。原因是新线程还为执行完毕或者说还未将flag修改为true的结果更新到主存中去,mian方法就执行到whlie循环部分,那么在主存中flag值为flase,一直在这里循环,直到cpu时间片被用完。MyThread线程得到cpu执行完毕。但是while(true)执行速度很快,重新得到cpu时间片后,不会从主从中去拿跟新后的flag值,只盯着自己缓存里面为flase的flag,那么陷入死循环。
为了让第一中情况更加明显,可以先让MyThread休眠0.2s,再去修改flag = true;则while循环基本上拿不到主存跟新后的flag。
在这里插入图片描述
执行结果基本上会是第一种情况,陷入死循环。
使用volatile修饰flag后,相当于直接在内存中修改flag值,这样while部分拿到的flag值一定为true。
执行结果:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值