volatile关键字的理解

文章讲述了Java内存模型JMM中的Volatile关键字如何确保线程间共享变量的可见性和有序性,以及防止指令重排的重要性。Volatile通过内存屏障来禁止特定类型的指令重排,以维护多线程环境下的正确性。文中还提到了对象创建流程和懒汉式单例模式中可能出现的问题,说明了volatile在此类场景的应用。
摘要由CSDN通过智能技术生成

JMM:(java内存模型)

 

Volatile保证线程间的共享变量可见性和有序性,可见性底层是基于lock指令实现的,  

计算机进行指令重排会基于as-if-serial和happens-before原则

as-if-serial:

就是说不管怎么重排,在单线程下,最终运行结构得和顺序运行结果相同,也就是说后面的语句不依赖于前面的语句,就可以重排,但是在多线程情况下,两个线程之间的依赖它实际是控制不了的,所以会出错。

happens-before:(8种,就是规定了8种原则不能重排序)比如

锁规则:就是说解锁一定要发生在同一个锁再一次调用之前

对象的创建流程:

先检查是否已加载类,没加载就加载,加载了就分配堆内存,然后初始化,设置对象头,执行init(C++实现)方法,其实在执行init方法时才是真正的进行赋值。比如说懒汉式单例模式,线程一加锁过后对对象进行创建,如果说指令重排将对象的创建地址分配提前了,而此时线程二进入进行第一次判断,发现该对象有地址,会误以为已经实例化,然后使用时发现对应属性还没有赋值,所以这里要使用volatile进行禁止指令重排

上述问题需要用到volatile,内存屏障:

内存屏障就是说在在放置内存屏障附近的代码不能进行指令重排,

四种屏障:用来避免指令重排,比如a是valatie修饰的变量

StoreStore屏障, 就是说在执行a=1操作之前有的语句要先执行

a=1; 对a进行写操作,则前面会加上StoreStore屏障

StoreLoad屏障, 就是说在执行之后的操作要保证a=1以及执行并刷入主内存,

b=a;对a进行写操作,在之后加上LoadLoad屏障

LoadLoad屏障,就是说b=a这个读取操作要在后续读取操作之前

LoadStore屏障,就是后续的对a进行写操作,要保证b=a读操作已经进行完

屏障的底层就是使用的lock指令

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值