volatile关键字用法和细节

本文深入解析Java中Volatile关键字的作用,包括确保线程间变量的内存可见性与禁止指令重排序,探讨其底层机制及在状态标记变量和单例模式双重检查锁定中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

volatile 修饰的共享变量,有两点特性

​ 保证了不同线程对该变量操作的内存可见性

​ 禁止指令重排序

java 中 所有的变量都存在主存中,每个线程又有自己的工作内存,

线程操作以工作内存为主,只能访问自己的工作内存,之后要把值同步到主内存中,

在执行的时候线程回去主存中读数据,然后加载到工作内存中,然后执行完在把值创给主存,主存的值就会更新

并发的三个特性:

​ 原子性:表示操作不可终端,要么一定执行完,要么不执行

​ 可见性:指的是一个线程修改数据,其他线程立刻能访问到

​ 有序性:即程序执行的顺序按照代码的先后顺序执行

volatile :

​ 是当变量修饰成volatile的时候,当读变量的时候,总是读到他的最新的值,不管那个线程对变量进行了写操作,都会立刻更新到主存中,

他保证了可见性和有序性,volatile限制了指令的重排序

当读一个volatile变量时,会把线程对于本地的内存置为无效,线程接下来将从主存中读取共享变量

但是他无法保证原子性,因为多个线程读去变量的时候,可能会被阻塞,

假设A读取值为10,被阻塞,B读取然后+1,就会变成11,

而因为A以及读到了数据,就不会去读最新的

volatile 底层机制:

​ 在生成汇编代码的时候会在volatile关键字的代码之前会有一个lock指令

它保证了,重排序的时候不能把后面指令重排序到这个位置之前

​ 会把cache写入内存

​ 写入动作会使别的内存无效cache,相当于让别的线程去读新写入的数值

使用场景:

​ 状态标记变量,因为对于标记变量只有赋值和读取,没有数据增加减少操作,会比上锁有一定效率提升

​ 单例模式里面的双重检查锁定,可以用它来修饰,因为也是只涉及到了读取它的状态

双重检查 ->多线程

如果你要共享的资源发生互斥的时候 并且是有判断什么时候结束

可以在已有锁的外面再加上一个上述的判断

这样当你已经满足这个判断的时候已经不用在进入锁住块的内部了

这样其他的线程在锁外的判断即满足 而不是在锁住等待了

可以提高效率

但是这样还是有瑕疵

但是这个方法还是有问题的因为你创建变量 new 这个对象的时候 这个变量又可能还是null

当有一个线程正好到new 这个对象的时候 你突然来一个线程调用这个方法

这个时候上一个线程 new了这个对象 但是还没完全初始化构造函数的时候

第二个线程会判断有这个对象 返回 然后第一个线程回来 发现还没new 利索

继续new 这个时候 两个对象还是不一样地址

作者拥有版权,请注明出处转载!

如果觉得有什么疑惑或者博主代码有什么问题,可以通过关于我,加我QQ联系 ,感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值