voliate关键字

voliate关键字详解:

1.内存模型相关概念

物理计算机内存访问图:
加粗样式
任何计算都是在CPU内处理的,那么也就必须涉及到数据读写,但是CPU每次都要和主内存交互读写数据效率太低了,于是有了高速缓存。在程序运行时,会从主内存中复制一份数据到高速缓存中,然后CPU在高速缓存中读写数据,计算完成后,再将结果从高速缓存中返回到主内存里。
在单线程中,上述操作是不会有问题的,但在多线程中就不行了
例如我们让两个线程都进行a=a+1的操作,按常理来说,结果会是2,但是有一下一种情况:
线程1和线程2都从主内存中读数据到高速缓存中,此时他们读的都是a一开始等于0的情况,然后分别在CPU中运算,线程1完成后,将结果a=1返回到主内存中。线程2完成运算后从高速内存将结果返回,还是a=1。那么结果就是两个线程分别做了加一运算,但是结果为1。
也就是说,一个变量在多个CPU中都有缓存就会出现:缓存不一致问题

2.Java内存模型

JMM(Java Memory Model)图:
工作内存其实是缓存、寄存器、编译器优化等笼统概念。
![是](https://img-blog.csdnimg.cn/449b3e9187ea45e688d9c708855ef8ef.png
Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。
这个图可以和物理计算机内存图类比,也会存在缓存不一致问题,并且Java中没有限制编译器为了提高效率对指令进行重排序,所以也会出现指令重排序问题

2.voliate关键字作用

为了解决Java缓存不一致和重排序问题,于是有了voliate关键字。
当一个共享变量被voliate修饰后

  1. 保证了这个变量再不同线程的可见性,一个线程修改了它,另一个线程立马知道
  2. 禁止指令重排序

前面说了,CPU会在缓存中读写数据,那么加了voliate关键字之后:

  1. 会将结果值立马写入主存
  2. 使其他线程对应变量的缓存无效,所以需要再次去主存中读取

我们用一段代码理解一下:

static class Counter {
    public int flag = 0;
}
public static void main(String[] args) {
    Counter counter = new Counter();
    Thread t1 = new Thread(() -> {
        while (counter.flag == 0) {
            // do nothing
       }
        System.out.println("循环结束!");
   });
    Thread t2 = new Thread(() -> {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入一个整数:");
        counter.flag = scanner.nextInt();
   });
    t1.start();
    t2.start();
}

t1线程会一直循环,t2线程会让用户输入一个整数,当用户输入0以外的值时,欲使t1线程循环结束。
但是执行结果是:输入5,t1线程仍在循环。
原因就是我们刚才所说的,t1线程一直读取的是工作内存的数据,工作内存中的flag任然是0,它没有意识到主存中flag的值已经为5了。
那么我们给flag用以voliate关键字修饰之后,就不会出现问题了。t2线程修改了flag值后会马上写入主存,t1线程工作内存的flag缓存会马上作废,从主存中读取flag的新值。

voliate不能保证原子性,它保证了内寸可见性和一定程度上的有序性
一定程度上的有序性是什么意思?
就是说加了voliate修饰的变量,对它的值进行修改的代码行相对位置不会变,不会受到指令重排序的影响
比如:
a,b,c,d没有被voliate关键字修饰
flag被voliate关键字修饰了

a=1;
b=2;
flag=5;
c=4;
d=6;

那么flag的位置一定会在a,b和c,d之间夹着。但是a,b的顺序可能调换,c,d的顺序也可能调换,所以是一定程度上的有序性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值