Java中的volatile关键字作用和底层原理

初步认识volatile关键字

  • volatile关键字是Java提供的弱同步机制,与synchronized不同,我们不经常使用它

volatile变量的两种特性

  • 变量可见性:被volatile修饰的变量对所有线程都保证可见,这里的可见指的是一旦有线程修改了该变量的值,其他线程能立即获取到该变量新的值
  • 禁止重排序volatile禁止了指令重排,指令重排简单来说就是JVM会在代码没有依赖赋值的地方打乱顺序执行,可能导致错误

volatile的使用场景和优缺点

  • volatile具有synchronized的可见性,但是并不具备原子性,这就使得volatile的使用条件受限,一般只能用于多个变量之间或者某个变量的当前值与修改后值之间没有约束的场景,就是必须满足以下两个条件:

    • 在这里插入代码片对变量的写操作不依赖于当前。
    • 该变量没有包含在具有其他变量的不变式中。

    比如 i++ 的这类(读取-修改-写入)操作,要求必须以原子方式完成,而volatile不能完成这一点,通常使用synchronized或者JUC包中的类来完成

  • volatile是比synchronized更轻量级的同步锁,在访问volatile的时候不会执行加锁的操作,因此就不会出现线程阻塞;当对非volatile 变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存中。如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同CPU cache中。而声明变量是volatile的,JVM 保证了每次读变量都从内存中读,跳过CPU cache这一步

volatile的底层实现原理

语言类型执行语句
Javavolatile= new Singleton();
汇编0x01a3de1d: movb $0x0,0x1104800(%esi);

0x01a3de24: lock addl $0x0,(%esp);

在汇编代码中的第二行代码执行时发生了两件事:

  • 将当前处理器缓存行的数据写回到系统内存
  • 这个写回内存的操作会引起在其他CPU里缓存了该内存地址的数据无效

处理器为了提高处理速度,不直接和内存进行通讯,而是先将系统内存的数据读到内部缓存后再进行操作,但操作完之后不知道何时会写到内存,如果对声明了Volatile变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。但是就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题,所以在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值