高并发下指令重排导致的单例方法异常

本文探讨了指令重排的概念及其在类加载和CPU执行层面的影响,特别是在高并发环境中可能导致的问题。以Java单例模式为例,当不使用`volatile`关键字时,可能出现线程安全问题,即指令重排可能导致未完全初始化的对象被其他线程访问,引发空指针异常。解决方案是使用`volatile`防止指令重排,确保线程可见性和有序性。
摘要由CSDN通过智能技术生成

场景描述

概念:

指令重排的时机:不是java文件被编译成class文件的过程。
1,是class文件被加载成二进制文件的过程中。字节码之类被翻译成机器码指令的过程中
2,cpu执行汇编指令的时候,会进行性能优化,也会进行指令重排。

指令重排序:java语言规范规定JVM线程内部维持顺序化语义。即只要程序的最终结果与
它顺序化情况的结果相等,那么指令的执行顺序可以与代码顺序不一致,此过程叫指令的重排
序。
指令重排序的意义是什么?JVM能根据处理器特性(CPU多级缓存系统、多核处理器等)
适当的对机器指令进行重排序,使机器指令能更符合CPU的执行特性,最大限度的发挥机器性
能。

概念的详细可参见此文档

单例方法例子:


 1. public class Singleton {
    
 2.       private static volatile Singleton myInstance;
 3.       public static Singleton getInstace() {
 4.          if (myInstance == null) {
 5.              synchronized (Singleton.class) {
 6.                    if (myInstance == null) {
 7.                        myInstance = new Singleton();
 8.                    }
 9.                }
 10.            }
 11.            return myInstance;
 12.        }
    
 13.    }

new一个对象的过程
请添加图片描述

  1. 在高并发的场景下 一个线程走到 第七行 myInstance = new Singleton();
    开始new这个对象,
  2. 此时如果发生指令重排 2和3步骤顺序对调了,另一个线程进来获取条件判断是可以获取到myInstance的,但是这个对象此时是未实例化的,会出现空指针异常。
  3. 方案之一是加上volatile关键字,标识这个对象禁止被指令重排。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值