深入理解Volatile

本文详细探讨了并发编程中的原子性、可见性和有序性概念,以及JMM如何与Volatile和Synchronized关键字关联,解释了Volatile如何保证可见性和有序性,以及与Synchronized的区别。

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

并发编程的核心

  1. 原子性
  2. 可见性
  3. 有序性

JMM 与三大特性之间的关系

原子性:所有的操作要么全部执行要么不执行

JMM 只保证简单的赋值和获取是属于原子性的(get i,set i ,i=0),Volatile关键字不能保证原子性。Synchronized关键字可以保证原子性,Jdk5以后提供原子类来保证原子性。

可见性:线程之间对共享变量可以感知变化

JMM对于可见性有以下几种方式保证

1.使用Synchronized关键字,保证在同一时刻只有一个线程获取锁执行。

2.使用Volatile关键字,保证多线程的情况下共享变量的操作永远是一致的。下面会具体分析。

3.使用Lock锁,同Synchornized保证同一时刻只有一个线程持有锁执行。

为什么volatile可以保证可见性?

Volatile关键字在Cpu的层面上以及有部分解释,可见性的原因是因为在多个线程内存储了共同一个被Volatile修饰的变量时,当有线程对它进行操作,其他线程的工作内存中该变量置为失效,必须从主内存中获取数据,从而保证可见性。

有序性

JMM对有序性也有如可见性一样的方式。

JMM本身也具备一些有序规则,具体规则如下:

0

JMM对于代码的执行顺序不一定保证从上至下的顺序,但它会保证结果如预期一致。

int i=2;
int y=4;
y=i+1;

如上结果:y=3,当在执行过程中有可能被JMM按照先执行了“int y=4”,再执行“int i=2”。这种情况称作为“指令重排序”

如果变量被Volatile修饰结果就会保证在执行到Volatile关键字时,前面的代码一定执行完了。

int x=1;
int y=4;
volatile int a=1;

如上:执行过程解释为有可能先“int y=4”->"int x=1"->"int a =1",也有可能先“int x=1”->"int y=4"->"int a =1",

思考:为啥Volatile会保证有序性以及它与JMM之间的关系是如何的?

源码分析Volatile:

从OpenJdk中的unsafe.cpp源码中,发现被Volatile修饰的变量存在一个:“Lock ; ”前缀,

“Lock ;”:前缀实际上是一个内存屏障,会对指令进行以下的保证:

  1. 确保在指令重排序时不会将其后面的指令放在内存屏障之前。
  2. 确保在指令重排序是不会将其前面的指令放在内存屏障之后。
  3. 确保在执行到内存屏障修饰的指令时,前面的指令已经全部执行。
  4. 强制将线程的工作内存中的值修改刷新值主内存。
  5. 如果是写指令那么其他线程的工作内存中的值会全部失效

Volatile的使用场景

  1. 线程的开闭状态利用可见性
  2. 状态标记 利用顺序性
  3. Single的double-check设计 利用顺序性

Volatile与Synchornized的区别

使用方式

volatile:只能修饰类变量与实例变量,不可以修饰常量,局部变量,方法,方法参数

synchornied: 不能对变量修饰,只能修饰方法和代码块

volatile修饰的变量可以Null而Synchornied同步代码块的mointer对象不能是Null;

可见性

volatile:是通过是用”Lock ;“ 内存屏障来保存的,强制将其他线程的工作内存的共享变量失效让他从主内存中读取。

synchornied:通过"monitor enter","monitor exit"对其他线程排他,保证同步代码变为串性化,在执行完"monitor exit"会将共享变量都刷新到主内存。

原子性

volatile:不能保证原子性

sync:通过对代码块进行加锁且不能再中途打断,因此保证了原子性。

顺序性

volatile: 通过内存屏障来禁止指令重排序,保证了有序性

sync:通过将同步代码块变为串性化来达到有序性

其他

volatile:不会阻塞线程

sync :其他线程在无法获取锁的情况下会阻塞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值