单例模式及线程安全的实践

🌟 欢迎来到 我的博客! 🌈

💡 探索未知, 分享知识 !💫

本文目录


引言

单例模式是个挺实用的设计模式,它的要点就是确保一个类只有一个实例 ,并且提供一个访问这个实例的全局点。这种模式在你需要控制资源或者保持全局状态的时候特别有帮助。但在多线程的情况下,实现这个模式就需要一些技巧,以确保安全和效率。下面咱们就一起看看怎么实现一个既安全又高效的单例模式。

基本的单例模式长啥样?

先来看一个最简单的单例模式示例:

java 复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

|----------------------------------------------------------------------------------|
| 这个例子简单明了,但在多线程的场景下就可能出问题了。比如,如果两个线程同时检查到 instance为空,那么它们就都会创建一个实例,这就不符合单例模式的初衷了。 |

PS :

就像图示中,这样就创建了多个实例对象

饿汉式单例

这段代码实现的是所谓的饿汉式单例模式。在这种模式下,单例的实例在类被加载到JVM时就立即初始化了。这种方式简单直接,因为它依靠JVM类加载机制保证实例的唯一性,同时也无需担心多线程问题,因为类加载过程是线程安全的。

java 复制代码
class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }

    private Singleton() { }
}

优点是实现简单,类加载时完成初始化,避免了线程同步问题。

缺点是如果这个类比较大,而且在程序启动时就加载,但长时间不使用,会导致资源浪费。


怎样才能线程安全?

|----------------|
| 可以给获取实例的方法加个锁: |

java 复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

这种方法虽然简单,但每次调用 getInstance() 都会加锁,可能会拖慢速度。

懒汉模式 ( 双 重 检 查 )

这个方法更聪明点,只在需要时加锁:

java 复制代码
public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

这样,只有在第一次创建实例时才会同步,提高了效率。而且,用了 volatile 关键字来确保变量的可见性。

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 这种方式的关键在于`instance`字段的`volatile`关键字和`synchronized`块。`volatile`确保当`instance`变量被初始化成单例实例时,多个线程正确地处理`instance`变量,`synchronized`块则确保在实例未初始化前只有一个线程能进入初始化代码区。 |

优点 : 只有在实际使用时才会创建实例。并且通过双重检查锁定机制减少了锁的粒度,提高了效率。
缺点 : 实现复杂,需要多重检查以确保线程安全。但我个人更推荐使用这种方法

🎉总结🎉

🎈在多线程环境下实现一个既安全又高效的单例模式需要一些技巧。根据你的需求和具体情况,你可以选择加锁、双重检查或者静态内部类的方法。如果你在乎性能,双重检查和静态内部类是不错的选择,因为它们在保证了线程安全的同时,也考虑到了效率。

相关推荐
Geometry Fu3 小时前
《物联网安全》第3.2章 无线传感器网络安全
物联网·安全·物联网安全·无线传感器网络·wsn
m0_738120724 小时前
渗透测试基础——黑盒测试下的Web漏洞挖掘与利用解析(一)
服务器·前端·网络·安全·php
碳基硅坊4 小时前
Qwen3.5-9B在安全生产安全帽检测中的应用
人工智能·安全·安全帽检测·qwen3.5-9b
小江的记录本5 小时前
【JVM虚拟机】类加载机制:类加载全流程:加载→验证→准备→解析→初始化(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·算法·安全·spring·面试
消失的旧时光-19437 小时前
企业认证与安全体系(四):企业登录认证流程全解析——JWT、Redis、Spring Security 如何协同工作?
redis·安全·spring·spring security·jwt
wb043072017 小时前
食安大检查——从阿明餐厅的突击检查,看安全架构的六大防线
安全·安全架构
不灭锦鲤8 小时前
网络安全第113天
安全·web安全
IT菜鸟程8 小时前
【银河麒麟V10】OpenSSH安全加固指南:源码编译升级至9.8p1版本
安全
阿昭L8 小时前
Windows认证和安全对象的基本概念
windows·安全
逸Y 仙X8 小时前
文章五:Elasticsearch安全通信
java·大数据·安全·elasticsearch·搜索引擎·全文检索·jenkins