单例模式

本文深入讲解单例模式的概念,分析其在确保唯一实例和全局访问点的优势,特别探讨懒汉式实现及其线程安全问题,提供加锁和volatile关键字解决方案。

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

1.单例模式概述

定义: 保证一个类仅有一个实例,并提供一个全局访问点

类型:创建性

使用场景:想确保任何状态下都绝对只有一个实例

优点:

1. 在内存中只有一个实例, 减少了内存的开销

2.避免资源多重占用

3.设置全局访问点,严格控制访问

2.单例模式的实现方式

1.懒汉式

    1)实现方法:


/**
 * 单例模式之懒汉式
 * */
public class LazySingleton {

    //静态私有的要被单利的对象(所谓懒汉式就是它比较懒,初始化的时候不创建)
    private static LazySingleton lazySingleton = null ;
    //私有的构造器 不让外部程序再次创建新的对象
    private LazySingleton(){
    }
    //公有静态获取实例的方法
    public static LazySingleton getInstance(){
        if(lazySingleton == null){
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}

2)非线程安全

但这种懒汉式实现的单例模式是线程不安全的 ,假设此时有两个线程,线程A走到

lazySingleton = new LazySingleton();

线程B走到

 if(lazySingleton == null){

当线程A还没有执行完时, 线程B判断lazySingleton 为null ,这样他就会再次执行new 操作, 那么这个对象就会被new 了两次。

3)解决方法

     方案1:

    我们在方法上添加synchronized 同步锁

 public synchronized static LazySingleton getInstance(){

 因为锁添加在静态方法上, 这样锁住的是整个类,每次请求这个方法时,都会判断一下这个锁,这样的效率是不高的

我们可以用双重检查机制,只有当这个对象为空的时候我们再锁住这个类

 public synchronized static LazySingleton getInstance(){
        if(lazySingleton == null){
            //只有当这个对象为空的时候我们才锁住这个类
            synchronized (LazySingleton.class){
                if (lazySingleton == null){
                    lazySingleton = new LazySingleton();
                }
            }
        }
        return lazySingleton;
    }

但这样其实也是线程不安全的 ,原因在lazySingleton = new LazySingleton()这行代码。 虽然这只有一行代码,但这行代码总共分为三个步骤  

                    1.分配内存给对象

                    2. 初始化对象

                    3. 设置lazySingleton 指向刚才分配的内存地址

但是2和3 有可能发生指令重排序 ,也就是3 走在2 的前面 , 在多线程的环境下, 虽然判断不为空, 但有可能对象并没有被初始化直接将这个对象返回 就会报错, 解决方法,添加 volatile 防止指令重排序

private volatile static LazySingleton lazySingleton = null ;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值