单例模式之懒汉式——》线程安全问题

本文深入探讨了单例模式在多线程环境下的实现,特别是如何利用Volatile关键字来确保线程安全和提高效率。同时,解析了Volatile在防止指令重排序和保证线程可见性方面的作用。

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

package com.zzfl.pm1;

/**
 * ZZFL 2019/8/11
 */
public class SingleTon {
    private SingleTon(){
        //禁止反射破解
        synchronized (SingleTon.class) {
            if (instance != null) {
                throw new RuntimeException("不能使用反射进行创建对象");
            }
        }
    }
    /*
    volatile:不稳定的,易挥发的。
     */
    private static volatile SingleTon instance;
    public static SingleTon getInstance(){
        if (instance == null) {//双重检测,提高效率
            synchronized (SingleTon.class) {//加锁,保证共享资源的原子性
                if (instance == null) {
                    instance=new SingleTon();
                }
            }
        }
        return instance;
    }
}
class Demo{
    public static void main(String[] args){
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                SingleTon singleTon=SingleTon.getInstance();
                System.out.println(singleTon.hashCode());
            }
        };
        new Thread(runnable, "窗口1").start();
        new Thread(runnable, "窗口2").start();
        new Thread(runnable, "窗口3").start();
        new Thread(runnable, "窗口4").start();
    }
}

对象在虚拟机中实例化的时候对多线程可能产生的影响

 

正常情况下,在创建一个实例化对象的时候,①首先是在堆中开辟空间,②然后调用构造方法对属性进行初始化,③最后把实例化对象地址赋值给栈空间中的变量。但是实际上在JVM运行的过程中有可能会对代码进行优化,优化成①③②。假如有一个线程A在进行实例化一个对象的过程中,被优化成①③②,但是当执行到步骤三的时候A线程的CPU此时到期,那么线程B在对该获取对象的时候,此时该对象时候通过判断发现该对象已经被实例化过了因为栈空间当中已经存有实例化对象的地址,但是由于A线程并没有对实例化对象属性进行初始化,因此在B线程获取该实例化对象的属性的时候有可能造成空指针异常。因此,如果对共享资源属性加上volatile修饰词进行修饰,那么就会告诉虚拟机不要对该实例化对象进行优化,而这个优化的过程就叫做指令重排序

volatile作用:

1)保证线程可见性

2)禁止指令重排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值