从双重校验锁进一步理解synchronized和volatile
并发编程中的四个问题:
可见性、原子性、有序性、指令重排
对于synchronized
和volatile
首先我们知道:
synchronized
可以保证原子性、有序性、可见性;
volatile
只能保证有序性和可见性,但是可以防止指令重排;
那这几个概念是什么意思呢?
什么是可见性?
问题:并发编程时,当一个线程对共享变量进行了修改,另外的线程并没能立即看到最新的值。
原因:本地内存缓存会保存数据副本,这就造成一个线程修改内存的变量后,其他的线程可能由于读取的是本地内存的缓存而造成了数据不一致。(就好像这个变量的改变其他线程看不到一样)
解决思路:对于这种变量,应该每次都去内存中读,而不是走缓存;volatile和synchronized都可以解决这个问题。
什么是原子性?
问题:对于num++这个语句,实际上分为三步执行;
1.获取num的值;
2.计算加一之后的值;
3.将新值赋给num;
在多线程中,这三步应该看作一个整体一块执行完,中间不应让另外的线程也执行这三个语句;否者就可能出现问题:
解决思路:在一个线程执行完该代码块之前,其他线程不能执行该代码块;synchronized可以解决这个问题。
什么是有序性?
保证线程串行地执行某个代码块,volatile和synchronized都可以解决这个问题。
什么是防止指令重排?
为了提升执行速度,计算机再执行代码的时候会对指令进行重新排序,并保证达到的最终效果是一样的(但是,但是,它只能保证在单线程没啥问题,当使用多线程时遇上指令重拍就可能出现问题了)
案例:双重校验锁(未禁止指令重排时)
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
//先判断对象是否已经实例过,没有实例化过才进入加锁代码
if (uniqueInstance == null) {
//类对象加锁
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
对于uniqueInstance = new Singleton();
语句其实是分三步走的:
- 为
uniqueInstance
分配内存空间 - 初始化
uniqueInstance
- 将
uniqueInstance
指向分配的内存地址
但是JVM进行指令重排后,执行过程可能就变成了1->3->2;在多线程环境下,就可能导致一个线程获得还没有初始化的实例。比如线程A执行了1和3,此时T2调用getUniqueInstance
后发现uniqueInstance
不为null,因此直接返回uniqueInstance
给其他程序使用,但实际上uniqueInstance
还没初始化呢,如果用的话肯定有问题。
解决:volatile
关键字可以禁止指令重排,因此双重校验锁正确的写法应该是:
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
//先判断对象是否已经实例过,没有实例化过才进入加锁代码
if (uniqueInstance == null) {
//类对象加锁
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
一些对比
关于volatile
和synchronized
的有序性需要说明一下,synchronized
保证的是代码块之间的有序性,确保多个线程串行地执行代码块,而对于代码块内部的有序是不保证的(也就是不会禁止指令重排);
总结:
volatile
:可见性、有序性、禁止指令重排
synchronized
:原子性、可见性、有序性
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具