多线程篇四——volatile关键字

多线程篇四——volatile关键字

如笔者理解有误,欢迎交流指正⭐


首先我们要明晰的一点是计算机运行程序或代码时经常要访问数据,这些依赖的数据往往存储在内存中.
CPU使用变量的时候需要先从内存中读取出来放到CPU的寄存器中.由此我们可得读内存比读硬盘快,读寄存器比读内存快,但是CPU一旦涉及读/写内存速率很低.此时我们聪明得编译器就会帮忙了(虽然有时候会帮倒忙) 编译器可能会对代码做出优化,减少读内存的次数。提高整体的效率.

volatile能保证内存可见性

上代码

import java.util.Scanner;

public class Demo14 {
    public static int flg = 0;
    public static void main(String[] args) {
         Thread t1 = new Thread(() -> {
            while(flg == 0) {
                //啥也没有
            }
             System.out.println("game over!")
         });
            Thread t2 = new Thread(()-> {
                Scanner sc = new Scanner(System.in);
                flg = sc.nextInt();
        });
            t1.start();
            t2.start();
    }
}

运行发现
img
当我输入6的时候,并没有输出"game over!" 按理来说修改flg的值不为0的时候会输出"game over!"为什么会出现异常呢?
这就是我们的内存可见性问题.
读取flg的值这个过程分为两步走.

1.load读取内存中的flg值到寄存器中.
2.通过cmp指令比较器比较缓存器的值是否为0,再决定是否要进入循环.

乍一看这么处理不也没什么问题。但是,while循环此时飞速运转短时间内会进行大量重复的操作,这样就出现了最开头介绍的小聪明编译器.big 胆就水灵灵优化上了😀
只在第一次循环的时候读内存后续直接从寄存器中取出数据

由于修改flg是t2线程非t1线程本身,编译器没有正确的判定(提高效率不保证逻辑不变哈)以为flg未被修改就直接启动优化了,t1感受不到修改过后的flg的内存变化

如何避免小聪明不要帮倒忙?这就需要聪明的你使用volatile关键字提醒编译器.【强制爱读取内存】
被volatile修饰的变量的的读写操作相关指令,是不可以重排序的.

import java.util.Scanner;

public class Demo14 {
    public static volatile int flg = 0;
    public static void main(String[] args) {
         Thread t1 = new Thread(() -> {
            while(flg == 0) {
                //啥也没有
            }
             System.out.println("game over!");
         });
            Thread t2 = new Thread(()-> {
                Scanner sc = new Scanner(System.in);
                flg = sc.nextInt();
        });
            t1.start();
            t2.start();
    }
}

当然解决内存可见性问题的方法出了从根部抹杀(volatile关键字)还可以规避问题(sleep延缓开销速率 优化也没必要进行了)

volatile不保证原子性

volatile 和 synchronized 有着本质的区别. synchronized 能够保证原子性, volatile 保证的是内存可见性.

volatile 和 synchronized 有着本质的区别. synchronized 能够保证原子性, volatile 保证的是内存可见性.


未完待续❀❀❀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值