volatile解决内存可见性问题

举一个例子先来了解什么是内存可见性问题

当编译器频繁使用比较操作,执行这个操作的时候,会出现下面两个操作

LOAD(将内存中的数据读取到CPU寄存器中)和CMP(在CPU寄存器中进行比较操作),要注意,这个过程很明显是LOAD操作要慢很多,因为内存中执行读写操作效率比寄存器中要慢的多,这个时候编译器就会自动优化,"不读内存,只读寄存器",意思是当频繁执行比较操作的时候,将后续LOAD操作进行省略,只读取第一次就行了.因为理论上进行循环操作时,变量值并没有发生变化.

下面给出了出现内存可见性问题的情况

public class Demo9 {
    static class Counter{
        public int count = 0;//修饰变量,不会触发优化操作
    }

    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread t1 = new Thread(() -> {
            while(counter.count == 0){

            }
            System.out.println("t1 执行结束");
        });
        t1.start();//负责读操作
        Thread t2 = new Thread(() -> {
            System.out.println("请输入一个 int:");
            Scanner scanner = new Scanner(System.in);
            counter.count = scanner.nextInt();
        });
        t2.start();  //负责写操作
    }
}

经过运行,当年输入的值将count值改正时,这时候程序仍然打印不了while循环中的下一个打印操作.

在这个过程中就发生了内存可见性问题,count只读取了开始的值(0).虽然后来count的值进行了修改,但是由于编译器优化的存在,不会读取修改后的值.所以就出现了线程不安全的问题

这个时候就需要使用volatile关键字,手动加上volatile语句的时候,这时候就会执行while循环下面的打印语句了,当然volatile不能保证原子性,只能保证内存可见性.

public volatile int count = 0;//修饰变量,不会触发优化操作

所以volatile禁止了编译器优化,避免了直接读取CPU寄存器中缓存的数据,而是每次都重新读取内存

JMM(Java内存模型)的角度看待volatile.

正常的程序执行的过程中,会把主内存的数据,先加载到工作内存中,在进行计算处理.编译器优化可能会导致不是每次都真的读取主内存,而是直接取工作内存中的缓存数据(可能会导致内存可见性问题)

volatile起到的效果就是保证内存都是真的从主内存中重新读取~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值