Java基础: volatile关键字相关特性

volatile是一个Java关键字,被其修饰的对象可以获得(简单的赋值与返回操作)的原子性和可见性(可视性)。

1. 原子性是什么?为什么可以获得原子性?

答: 原子性一般针对于原子操作而言,这是一种不能被线程调用机制中断的操作,一旦操作开始,那么它一定可以在可能发生的"上下文切换"之前执行完毕。举个例子,jvm会自动将64位的long和double类型变量的读取或者写入当做两个独立的32位操作来执行,这就产生了在读取和写入之间发生线程上下文切换的可能(产生字撕裂)。若使用volatile,会使得jvm放弃这种优化,直接对变量进行一步读取或写入。

2. 什么是可见性?为什么volatile可以保证可见性?

答: 可见性是针对多个任务而言。在多线程环境下,不同的任务每次都从主存(而不是本地处理器的缓存)中获取被volatile修饰的对象,从而实现了每次获取的对象都是最新的,这就是可见性。volatile为对象的读取操作前增加了一道读屏障,写入操作后增加了一道写屏障,尽最大努力保证: 1. 写入前,所有之前发生的事情已经发生,并且任何更新过的数据都能看到最新的值。2. 写入后,任何其他线程中的任务都能获取到该对象最新的值(因为写屏障会将数据强制从本地处理器的缓存中刷新至主存)。

3. 为什么i++不是原子性操作,即便使用volatile也无济于事?

答: 因为i++这种自增操作在jvm中被拆分成了三个步骤执行(并非是jvm优化导致的),分别是:

     step1: 读取volatile变量的值到本地寄存器。

     step2: 对i进行算数运算。

     step3: 将最新的i回写至主存中。

通过javac -p指令可以得到以下编译后的代码

mov   
0xc(%r10),%r8d
 ; Load
inc   
 %r8d           ; Increment
mov   
 %r8d,0xc(%r10)
 ; Store
lock
 addl $0x0,(%rsp)
 ; StoreLoad Barrier

在Load(加载,也就是读取)和Store(存储,也就是写入)这两步操作之间,有4步额外的操作,如果其他cpu驱动的线程在当前线程执行这4步时对对象进行了更新,则在当前线程执行完Store操作后,其他线程更新数据将会被丢失(覆盖)。

分割线...................2021年7月补充........................

volatile不是轻量级锁,它仅仅只能保证可见性。

锁的意思是,我在获取一个资源时,其它人都不能获取这个资源。所以锁必然能保证原子性。但是volatile不能保证原子性,所以volatile不是锁!                                                                        

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值