单例模式详解:如何优雅地实现线程安全的单例

一、什么是单例模式?

单例模式是一种常用的设计模式,目的就是确保某个类在程序中只有一个实例,并且提供一个全局访问入口。通过这个模式,我们能够保证全局共享同一个对象实例,避免了多次实例化同一个对象,节省内存,提升性能。

二、单例模式的优点

  1. 节省内存与计算资源
    单例模式确保只会创建一个对象实例,避免了多次创建同一个对象,减少了内存和计算资源的消耗。

  2. 方便管理与控制
    对象的管理变得更加集中,能够方便地对单例对象进行控制与管理,特别适用于全局共享的资源,比如数据库连接池、日志记录器等。

  3. 线程安全
    单例模式常常与多线程环境配合使用,确保多线程情况下只能有一个实例创建,避免了线程安全问题。

三、线程安全的单例模式实现

在多线程环境下,我们通常需要保证单例实例的创建是线程安全的。下面是使用“双重检查锁”实现线程安全的单例模式代码:

public class Singleton {private static volatile Singleton singleton;// 私有构造函数,防止外部通过new来创建实例private Singleton() {}// 获取单例对象的方法public static Singleton getInstance() {// 第一层检查,避免不必要的同步if (singleton == null) {synchronized (Singleton.class) {// 第二层检查,确保只有第一个线程创建实例if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

四、为什么需要“双重检查锁模式”?

在上述代码中,我们使用了双重检查锁(Double-Checked Locking)来确保线程安全并优化性能。理解为什么需要两次 if 判断,首先要了解以下几个方面:

1. 第一个 if 判断

  • 目的是避免不必要的同步。当第一个线程进入时,实例还未创建,它会进入 synchronized 块去创建实例。而如果实例已经被创建,后续的线程就无需进入同步块,直接返回已有实例,从而提高性能。

2. 第二个 if 判断

  • 保证单例唯一性。假设有两个线程 A 和 B 都同时执行了第一个 if 判断,并且都发现 singleton == null。此时,线程 A 获得了锁并创建了实例,而线程 B 在等待锁的过程中,也会经过第一次 if 判断,并进入同步块,但此时线程 A 已经创建了实例。
  • 如果没有第二个 if 判断,线程 B 也会重新创建一个新的实例,这就破坏了单例模式的初衷。

五、为什么需要 volatile 关键字?

在这段代码中,我们给 singleton 加上了 volatile 关键字。volatile 在这里的作用是保证线程之间的可见性,防止指令重排序带来的问题。

1. singleton = new Singleton() 不是原子操作

在 JVM 中,执行 singleton = new Singleton() 至少包含以下三步:

  • singleton 分配内存空间
  • 调用 Singleton 的构造函数初始化对象
  • singleton 引用指向分配的内存空间

在多线程环境下,JVM 可能会对这三步指令进行重排序。假如指令重排序导致 singleton 被赋值为空(第3步)但对象还未初始化完成(第2步未完成),这会导致其他线程误以为 singleton 已经初始化完成,从而访问一个未完全初始化的对象。

2. volatile 保证可见性

volatile 可以避免指令重排序,从而确保在一个线程中对 singleton 的修改对其他线程立即可见,确保单例实例只会被初始化一次。

六、总结

单例模式在保证程序中对象的唯一性和全局访问的同时,能够有效节省资源、提高效率。在多线程环境下,我们通过“双重检查锁模式”来确保单例的线程安全,并通过 volatile 关键字保证对象的可见性和防止指令重排序。

通过以上的学习,你应该已经理解了如何优雅地实现一个线程安全的单例模式。这个实现方式不仅性能优越,而且能够在多线程环境中有效防止并发问题,是许多高并发系统中不可或缺的设计模式之一。

🌟 关注我的CSDN博客,收获更多技术干货! 🌟

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大学生福音!用gpt-4o和o1大模型拿捏大学化学作业

文章目录 零、前言一、使用GPT操作指导作业拍照使用o1-preview大模型小结 二、感受 零、前言 昨天发了gpt-4o拿捏大学物理作业,群友说,急需要一位化学老师指导 虚竹哥是宠粉的,连夜请了一位博士级的化学老师~ 一、使用GPT 操作指导 ChatG…

2024-11-12 学习人工智能的Day25 scikit-learn库初见

简简单单的数据集 from sklearn.datasets import load_iris/fectch 简单的引用世界数据集和玩具数据集方式 #下面是在获取数据集后常用的值 feature feature_names DESCR target target_names filename from sklearn.datasets import load_iris import numpy as np import…

2024 年将 Postman 文档导出为 HTML 或 Markdown

2024 年将 Postman 文档导出为 HTML 或 Markdown

访问网页的全过程(知识串联)

开发岗中总是会考很多计算机网络的知识点,但如果让面试官只靠一道题,便涵盖最多的计网知识点,那可能就是 网页浏览的全过程 了。本篇文章将带大家从头到尾过一遍这道被考烂的面试题,必会!!! 总…

服务器硬件介绍

计算机介绍 现在的人们几乎无时无刻都在使用电脑!而且已经离不开电脑了。像桌上的台式电脑(桌机)、笔记本电脑(笔电)、平板电脑、智能手机等等,这些东西都算是电脑。 台式机电脑介绍 计算机又被称为电脑。台式机电脑主要分为主机和显示器两个部分&…

04-HTTP协议、请求报文、响应报文

欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…

基于Multisim人数出入加减计数统计电路(含仿真和报告)

【全套资料.zip】人数出入加减计数统计电路Multisim仿真设计数字电子技术 文章目录 功能一、Multisim仿真源文件二、原理文档报告资料下载【Multisim仿真报告讲解视频.zip】 功能 设计两路光控电路,一路放置在入口,另一路设置在出口,当有人…

车机安装第三方软件实现打开软件全屏教程

简介 越来越多的车友实现安装第三方软件了,但是有的车机的状态栏或者导航栏会遮挡安装的第三方软件。这样的话,第三方软件就会显示不全,体验感非常不好。所以,下面我教一下大家如何使用东君应用管家来实现打开第三方软件全屏。 全…

CLion配置QT开发环境

一、将qmake工程转为cmake工程(方法一:用工具转换并做适当修改) 1、工具链接:链接:https://pan.baidu.com/s/1grW2QY3sW8X2JaHWM_ePPw 提取码:7at4 工具源码:https://github.com/milahu/qmake2cmake 2、执行…

第3章-需求 3.4 需求的合法合规性审查

3.4 需求的合法合规性审查 3.4.1 项目需求的合法性审查3.4.2 委托研发项目的法律问题3.4.3 项目实施过程中的知识产权问题1.开发成果的知识产权保护2.开发过程中的侵权风险防控 近年来随着依法治国的深度开展,企业合规的概念越来越多地出现在大众眼前,也…

怎么保护源代码,源代码防泄密的十种方法

在现代软件开发中,源代码被视为企业的“数字资产”,它不仅承载着企业的核心竞争力,更是推动技术创新和业务发展的基石。然而,随着信息技术的普及和开发环境的复杂化,源代码泄密的风险也在不断增加。保护源代码的安全已…

单相锁相环,原理与Matlab实现

单相锁相环基本原理 单相锁相环的基本原理图如下所示, u α u_\alpha uα​ u β u_\beta uβ​经Park变换、PI控制实现对角频率 ω \omega ω和角度 θ \theta θ的估算。不同锁相环方案之间的差异,主要表现在正交电压 u β u_\beta uβ​的生成&#x…

腾讯云双十一福利篇之CVM云服务器

🍋引言 随着企业数字化转型的不断深入,对云计算的需求日益增长。腾讯云推出的云服务器(CVM)为企业提供了一种灵活、高效、经济的计算服务解决方案。CVM云服务器不仅能够快速响应业务需求,还可以帮助企业降低前期硬件投…

DDei在线设计器-国际化

国际化 从1.2.42版开始,DDei提供了国际化支持。默认提供了中文/英文两种语言。 编辑器会读取浏览器的语言设置,也能够在初始化时强行指定,默认使用zh_CN(中文)。 本示例基于教程快速指南开发,如果您不清楚怎样引入DDei设计器,请查…

NUXT3学习日记一(在我git中拉取代码、文件讲解)

Nuxt 3 是一个基于 Vue 3 的现代框架,用于构建服务器端渲染(SSR)和静态生成的应用程序。它提供了一种简化的方式来创建高性能的 Vue 应用,具有许多强大的功能和优点。以下是 Nuxt 3 的一些主要应用和优点: 一、应用场…

小米路由器3(R3)安装mixbox命令

sh -c /extdisks/sda1/ftp/install.sh && source /etc/profile &> /dev/null install.sh文件 或者在目录新建一个粘贴 #!/bin/sh -e #copyright by monlorclear logsh() {# 输出信息到/tmp/messages和标准输出logger -s -p 1 -t "$1" "$2&quo…

DAY27|贪心算法Part01|LeetCode:455.分发饼干、376. 摆动序列、53. 最大子序和

贪心算法 贪心的本质是选择每一阶段的局部最优,从而达到全局最优。 贪心算法并没有固定的套路,最难想的就在于如何通过局部最优去推出全局最优。在做一个题目的时候,靠自己手动模拟,如果模拟可行,就可以试一试贪心策略…

“反卷”风暴席卷双十一,商家们却卖爆了

文丨郭梦仪 11月12日零点,第16届双11落下帷幕,但商家的故事依然在继续。 “今年双11,没想到能月入千万,流量上升了200%。”乐尘家居主理人子旭向商业数据派表示,他今年最明显的感受是,认真经营的人在这个…

OCCT7.7.0 使用VTK9.2.0

1.前言 OCCT使用的VTK版本是VTK6.1.0,这个版本已经比较老了,如果要使用新版本的VTK,则需要自己引入新版本VTK,自己编译,我这里也比较好奇,为什么OCCT不升级一下VTK版本,下面自己来引入VTK9.2.0…

STM32项目实战:基于STM32U5的火灾报警系统(LVGL),附项目教程/源码

《火灾报警系统_STM32U5》项目完整文档、项目源码,点击下方链接免费领取。 项目资料领取https://s.c1ns.cn/F5XyU STM32项目实战之“火灾报警系统”(基于STM32U5) 今天小编来分享一个《火灾报警系统》的项目案例,硬件平台是STM…