Java中volatile关键字语义

本文主要介绍Java中volatile变量的内存语义。volatile变量有保证线程可见性和禁止指令重排序优化两种特性,是JVM最轻量的同步机制。还阐述了其实现机制,以及写和读操作的内存语义,同时指出在不满足特定规则的运算场景中使用需加锁同步。

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

volatile的内存语义

volatile变量有两种特性:

  1. 保证此变量对所有的线程的可见性
  2. 禁止指令重排序优化

 

简单来说,把对volatile变量所有的单个读/写,看成是使用了同一个锁对这些单个的读/写操作进行了同步,当然,实现上并不是这样的。volatile变量是JVM提供的最轻量的同步机制。

 

volatile变量实现机制

转换成指令的时候,我们可以发现,volatile变量在每次save操作的时候,和普通的变量相比,都会多一个lock命令,这个命令会使得发生以下两件事:

  1. 将当前处理器缓存行的数据协会到内存系统;
  2. 这个写回内存的操作会使得其他CPU里缓存的该内存地址的数据失效。

 

volatile变量在不满足以下两条规则的运算场景中的使用都需要通过加锁来实现同步:

  1. 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值;
  2. 变量不需要与其他的状态变量共同参与不变约束。

 

针对上面说的1)我们可以知道为何对于volatile修饰的int变量直接做加一或者减一的操作是线程不安全的了,因为运算结果依赖当前值。

 

volatile变量写的内存语义:

当写一个volatile变量的时候,JMM会把该线程对应的工作内存中的共享变量值刷新到新的主内存。

volatile变量读的内存语义:

当读一个volatile变量的时候,JMM会把该线程对应的工作内存设置为无效,线程接下来从主内存中读取对应的变量。

### Java 中 `volatile` 关键字在懒汉式单例模式中的作用 在懒汉式单例模式中,`volatile` 关键字用于确保多线程环境下的可见性和有序性。当一个线程修改了 `instance` 的值时,其他线程能够立即看到这个变化[^1]。 具体来说,在双重检查锁定(Double-Checked Locking)的实现中,如果没有使用 `volatile`,可能会遇到指令重排序的问题。JVM 可能会对初始化过程进行优化,使得对象的部分构造先于完全构造完成前暴露给其他线程。这可能导致其他线程读取到未完全初始化的对象实例,从而引发潜在错误。通过声明 `private volatile static Singleton instance;`,可以防止这种情况发生,保证即使在一个线程完成了对象的创建之后,另一个线程也能正确无误地获得已经完全初始化好的对象引用。 ```java public class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } ``` 在这个例子中,`volatile` 确保了两个方面: - **可见性**:一旦某个线程成功设置了 `instance`,那么所有后续对该字段的读操作都将返回最新的值。 - **禁止指令重排序**:编译器不会对涉及 `instance` 字段的操作做任何可能破坏程序语义的重新排列。 因此,`volatile` 是实现线程安全且高效的懒汉式单例模式的关键要素之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值