Java后端
·2025-11-11学习笔记
。
接下来,关于并发编程还有最后一个问题,就是有序性问题。
什么是有序性,有序性就是高级语言程序的一条代码或者是实现这条代码的多个CPU指令,按照先后顺序,有序的进行。但是,我们的编译器有一个编译优化的机制,这个机制为了提升性能,有时会改变代码执行的先后顺序,或者是改变CPU指令执行的先后顺序,这在实际场景中,就会给我们带来困扰,下面举个例子看看这到底是个什么问题。
经典的例子就是双检锁单例模式创建单例对象的时候了
public class Singleton{
private Singleton instance;
private Singleton getInstance(){
if(instance==null){
synchronzied(Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
我们先讲instance = new Singleton()这一语句是怎么通过CPU指令去实现的,(1)分配一块内存M (2)在内存M上初始化对象Singleton (3)将内存M的地址赋值给instance。正常来说是按照这三步指令顺序执行。但是,由于编译器的编译优化机制,它的执行顺序实际上可能是(1)-》(3)-》(2)。那么就会出现问题了。
假设有两个线程A,B,线程A先执行这个getInstance方法,线程A经过了第一层判空,去抢夺锁的资源,线程A拿到锁,于是线程A经过第二层判空,执行instance=new Singleton();但是在执行CPU指令的时候,是按照1)-》(3)-》(2)的顺序去执行,当执行完CPU指令(3),但是还没有执行CPU指令(2)的时候,恰好!发生了线程切换,线程切换到了线程B,线程B也执行了这个getInstance方法,但是在第一层判空的时候,instance!=null,于是继续往下执行,去使用了这个没有初始化Singleton对象的instance对象,就会出现空指针异常。这就是有序性问题。
由于线程切换以及CPU只保证CPU指令的原子性,会出现原子性问题。
由于不同CPU的缓存之间不可见,就会出现可见性的问题
由于编译器的优化机制导致的执行重排序,会出现有序性问题
2
0
分享
操作
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
