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

🌟 欢迎来到 我的博客! 🌈

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

在这里插入图片描述

本文目录

    • 引言
    • 基本的单例模式长啥样?
    • 怎样才能线程安全?
      • **懒汉模式** ( 双 重 检 查 )
    • 🎉总结🎉


引言

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

基本的单例模式长啥样?

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

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类加载机制保证实例的唯一性,同时也无需担心多线程问题,因为类加载过程是线程安全的。

class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }

    private Singleton() { }
}

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

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


怎样才能线程安全?

可以给获取实例的方法加个锁:
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

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

懒汉模式 ( 双 重 检 查 )

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

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`块则确保在实例未初始化前只有一个线程能进入初始化代码区。

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

🎉总结🎉

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/448351.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

动态代理详解(原理+代码+代码解析)

动态代理 1.什么是动态代理? 动态代理是一种在运行的时候动态的生成代理对象的技术。它在不改变原始类的情况下,对原始类的方法进行拦截或者增强。 2.动态代理可以实现的功能? 使用动态代理可以实现如下常用功能: 1.AOP&#x…

为什么要使用数字档案管理系统

机关企事业单位使用数字档案管理系统,主要有以下几个原因: 1. 档案管理效率提升:玖拓智能数字档案管理系统可以帮助综合档案馆实现对档案的全面管理和翔实记录,包括档案的入库、整理、检索、借阅等工作。系统化的管理使得档案管理…

调整分区失败,硬盘难启:原因分析与数据恢复之道

在数字化时代,硬盘作为存储数据的重要工具,其稳定性和安全性至关重要。然而,有时在调整分区的过程中,我们可能会遭遇失败,导致硬盘无法打开,数据无法访问。这种情况不仅令人沮丧,更可能带来不可…

第16章——西瓜书强化学习

在强化学习中,智能体通过与环境的交互来学习如何做出决策。在每个时间步,智能体观察当前的环境状态,并根据其策略选择一个动作。环境会对智能体的动作做出响应,并给出一个奖励信号(reward),该信…

crossover玩不了qq游戏大厅怎么办 仍有五亿人坚持用QQ crossover玩游戏 Mac电脑玩QQ游戏

从1999年2月,QQ首个版本QICQ(OPEN-ICQ)上线。到2024年,靠着5亿月活用户,守住社交领域TOP2位置。你还记得QQ经典的铃声吗? 根据月狐数据2023年12月的统计,QQ月活跃账户数比微博和知乎加在一起还要…

【C++庖丁解牛】STL之vector容器的介绍及使用 | vector迭代器的使用 | vector空间增长问题

📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 目录 1.1 vector的介绍2 v…

创造一款安卓自定义控件(4)——使用Matrix的setPolyToPoly方法实现图像纠正

接上文: 创造一款安卓自定义控件_任意4顶点裁剪框http://t.csdnimg.cn/vu1r5 创造一款安卓自定义控件_任意4顶点裁剪框2_为裁剪框添加放大镜功能http://t.csdnimg.cn/qkngh 创造一款安卓自定义控件_裁剪原理介绍http://t.csdnimg.cn/ORRRL 需求 随着需求修改&#x…

Linux系统部署火狐浏览器结合内网穿透实现公网访问

目录 前言 1. 部署Firefox 2. 本地访问Firefox 3. Linux安装Cpolar 4. 配置Firefox公网地址 5. 远程访问Firefox 6. 固定Firefox公网地址 7. 固定地址访问Firefox 结语 前言 作者简介: 懒大王敲代码,计算机专业应届生 今天给大家聊聊Linux系统…

企业接入SD-WAN组网需要花费多少?

企业数字化转型的不断深入,越来越多的企业开始考虑采用SD-WAN(软件定义广域网)技术来优化其网络架构,提升网络性能和安全性。然而,对于企业来说,接入SD-WAN组网 需要花费多少是一个关键问题。以下是一些影响…

对接钉钉机器人实现点餐提醒,妈妈再也不用担心我错过点餐了

公司的点晚饭时间是11点半到下午3点。忙起来真的很容易忘记,今天话不多说,直接开搞一个机器人提醒我们点饭 ::(笑眼) 。本教程基于centos7版本 “前提要有一个服务器 和一个钉钉群” 要对接钉钉机器人,首先你要有钉钉的群。假设你已经有了钉…

算法——哈希王

242.有效的字母异位词 力扣题目链接(opens new window) 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true 示例 2: 输入: s "rat", t "car&qu…

错误:npm ERR! code CERT_HAS_EXPIRED 解决

问题: 在打开项目用npm install安装依赖时报错:npm ERR! code CERT_HAS_EXPIRED如下图: 原因: 说明正在尝试访问的npm registry 淘宝npm镜像源 的SSL证书已经过期,导致无法建立安全连接。 解决: 配置不…

从内存管理的角度聊聊MMU的那些事

本文从内存管理的发展历程角度层层递进,介绍 MMU 的诞生背景,工作机制。而忽略了具体处理器的具体实现细节,将 MMU 的工作原理从概念上比较清晰的梳理了一遍。 MMU 诞生之前: 在传统的批处理系统如 DOS 系统,应用程序与操作系统在内存中的布…

如何选择海外代理ip?需要注意哪些因素?

选择合适的海外代理ip提供商是确保网络活动安全、高效和顺畅的关键。在众多提供商中做出明智选择需要考虑多个关键因素。 首先,讨论如何选择合适的海外代理ip服务提供商。一个好的服务提供商应该具备良好的市场声誉和客户反馈。在选择前,深入研究并比较…

【Java设计模式】九、桥接模式

文章目录 0、背景1、模式2、案例3、使用场景 0、背景 现要创建不同的图形,图形的形状有圆、长方形、正方形,且它们有不同的颜色 两个维度在变,使用类的继承可以实现,也符合开闭原则,但会类爆炸。 1、模式 将抽象与…

什么是高级编程语言?——跟老吕学Python编程

什么是高级编程语言?——跟老吕学Python编程 高级编程语言简介高级编程语言发展历程高级编程语言特点高级编程语言分类命令式语言函数式语言逻辑式语言面向对象语言 常见的高级编程语言及其特点和应用领域高级编程语言性能分析高级编程语言的工作方式 高级编程语言简…

【框架设计】MVC和MVVM对比图

1. MVC(Model-View-Controller) 单向通信View和Model通过Controller承上启下 2. MVVM(Model-View-ViewModel) 数据绑定M -> VM -> V DOM事件监听 V -> VM -> M 1. MVC是单向的,MVVM是双向的,…

服务器主机云主机在日常维护需要注意的几个点

服务器的日常维护对于确保服务器的稳定运行和安全性非常重要,以下是一些常见的服务器日常维护方面: 定期更新操作系统和软件:确保服务器的操作系统、应用程序以及安全补丁都是最新的,以填补已知的安全漏洞和提高系统性能。监视服务…

Stable Diffusion 详解

整体目标 文本生成图片;文本图片生成图片 网络结构 CLIP的文本编码器和图片生成器组成图像生成器,输入是噪声经过UNet得到图像特征,最后解码得到图像 前向扩散 模型直接预测图片难度比较大,所有让模型预测噪音然后输入-噪音…

MaxEnt模型与R语言结合:物种分布模拟的案例分析

在生态学研究中,物种分布模拟是一项至关重要的任务。它有助于我们理解物种与环境之间的复杂关系,预测物种在气候变化或人类活动影响下的潜在分布变化。近年来,随着计算机技术的不断发展,基于机器学习的物种分布模拟方法逐渐成为研…