线程安全的懒加载单例模式

一、什么是单例模式

单例模式是一种设计模式,它确保某个类只有一个实例,并提供一个全局访问点来获取该实例。这种模式在多种编程语言中都有实现,包括Java和C++。单例模式的实现可以采取饿汉式或懒汉式两种方式。饿汉式是在类加载时就创建了实例,而懒汉式则是在首次使用时才创建实例。懒汉式在多线程环境下可能会遇到线程安全问题,需要额外的线程安全措施来保证单例对象的唯一性。

在Java中,单例模式的实现可以通过私有构造函数、静态私有对象和静态公有函数来实现。

二、编写线程安全的懒加载单例模式

1、单例模式

//单例类:打印机
class Printer{
    //提供静态的私有属性
    private static Printer instance = null;

    //私有的构造方法
    private Printer(){

    }

     //向外部提供创建对象的静态方法
    public static Printer getInstance(){
        return new Printer();
    }
}

2、懒加载

实现懒加载,就是在使用的时候才创建,修改提供对象方法:


     //向外部提供创建对象的静态方法
    public static Printer getInstance(){
        //判断私有的静态对象是否为空
        if(instabce == null){
            //空则创建新对象
            instance = new Printer();
        }
        return instance;
    }

3、线程安全

多线程环境下上述代码存在问题,仍然可能导致对象被多次创建,所以需要加锁,避免多个线程同时创建对象,修改提供对象方法:


     //向外部提供创建对象的静态方法
    public static Printer getInstance(){
        //判断私有的静态对象是否为空
        if(instabce == null){
            //加锁,避免对象被多个线程同时创建
            synchronized(Printer.class){
                //空则创建新对象
                instance = new Printer();
            }
        }
        return instance;
    }

在创建对象的代码块上加上了synchronized阻塞锁,但多个线程同时进入 if 判断里面,对象仍会被多次创建,所以我们需要在加锁的代码块中再次判断,修改代码:


     //向外部提供创建对象的静态方法
    public static Printer getInstance(){
        //判断私有的静态对象是否为空
        if(instabce == null){
            //加锁,避免对象被多个线程同时创建
            synchronized(Printer.class){
                //再次判断
                if(instance != null){
                    return instance;
                }
                //空则创建新对象
                instance = new Printer();
            }
        }
        return instance;
    }

三、单例模式的应用场景

单例模式的应用非常广泛,包括但不限于线程池、缓存、日志、对话框、打印机、显卡的驱动程序对象等。这些应用通常需要管理系统的全局资源,避免出现不一致的状态或浪费资源的情况。

此外,单例模式也有其缺点,例如没有接口导致扩展困难,以及在特定情况下可能会浪费内存资源(如饿汉式实现在类加载时就创建了实例)。因此,在设计单例模式时需要权衡其优缺点,根据具体的应用场景来选择合适的实现方式。

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

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

相关文章

sky18流水线设计

1.最大时钟频率确定 时钟周期要大于等于组合逻辑的delay(最大的那条delay) Freq_max(Mhz) 1000/T_delay(ns); 数据吞吐率Throughput Freq_max *Toggle_rate;//Toggle_rate:如两个时钟,输入变一次,就是50%&#xff1b…

【考研408计算机组成原理】微程序设计重要考点指令流水线考研真题+考点分析

苏泽 “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家 目录 微指令的形成方式 微指令的地址形成方式 对应考题 题目:微指令的地址形成方式 - 断定方式 解题思路: 答题: 分析考点&…

大模型系列课程学习-基于2080TI-22G魔改卡搭建双卡大模型训练平台(双系统)

1.选择合适的硬件配置 再配置电脑之前,需要确认自己需要的显存大小、主板、内存条、电源、散热等核心配件。经过前期调研,选择的硬件配置如下: (1)主板:华南X99_F8D(DDR4主板),因为需要支持双卡…

1Panel运维利器:功能详解与实操指南

官网地址:https://1panel.cn/ 1Panel简介 1Panel是杭州飞致云信息科技有限公司旗下产品,是一款现代化、开源的Linux服务器运维管理面板,于2023年3月推出。 名称:1Panel开源Linux面板 所属公司:杭州飞致云信息科技有限公司 编写语…

基于HarmonyOS NEXT开发智能提醒助手

目录 目录 目录 前言 关于HarmonyOS NEXT 智能提醒助手需求分析 智能提醒助手设计 1、系统架构 2、功能模块 智能提醒助手的应用场景 智能提醒助手的竞争力 具体技术实现 未来展望 结束语 前言 随着智能设备的普及和物联网技术的飞速发展,人们对于智能…

忙忙碌碌的混沌之中差点扑了个空而错过年中这条线

文章目录 前言初见端倪混沌初始力不从心心力交瘁拾遗补缺总结 前言 突然意识到过完这个周末已经7月份了,他预示着我的2024年已经过半了,过年回家仿佛还是昨天的事情,怎么转眼间已经到了年中了。心里还是不愿承认这件事,翻开自己2…

Nacos配置中心客户端源码分析(一): 客户端如何初始化配置

本文收录于专栏 Nacos 推荐阅读:Nacos 架构 & 原理 文章目录 前言一、NacosConfigBeanDefinitionRegistrar二、NacosPropertySourcePostProcessor三、AbstractNacosPropertySourceBuilder总结「AI生成」 前言 专栏前几篇文章主要讲了Nacos作为服务注册中心相关…

github主页这样优化,让人眼前一亮

我的主页(一之十六) 1. 创建与账户ID同名的仓库 注意:记得勾选Add a README file 2. markdown语法自定义README.md 3. 辅助工具 优秀profile:https://zzetao.github.io/awesome-github-profile/动态文字:https://r…

SpringMVC(1)——入门程序+流程分析

MVC都是哪三层?在Spring里面分别对应什么?SpringMVC的架构是什么? 我们使用Spring开发JavaWeb项目,一般都是BS架构,也就是Browser(浏览器)-Server(服务器)架构 这种架构…

谷歌开发者新号上架攻略:开发者实战经验分享

前段时间,不少开发者朋友们在纷纷在吐槽新账号没法上架成功。以前谷歌对新号是真的很严格,但现在情况似乎有所好转。 今天,和大家聊聊如何在新号成功上架上“快人一步”,以及怎样增加账号权重提高上架成功率。 首先,我…

成绩发布背后:老师的无奈与痛点

在教育的广阔天地里,教师这一角色承载着无数的期望与责任。他们不仅是知识的传播者,更是学生心灵的引路人。而对于班主任老师来说,他们的角色更加多元,他们不仅是老师,还必须是“妈妈”。除了像其他老师一样备课、上课…

Linux文件系统与设备文件

一、Linux文件操作 Linux的文件系统API主要涉及创建、打开、读写、定位、关闭文件 创建 int creat(const char *filename, mode_t mode);mode: 代表新建文件的存取权限,需要和umask相与才能确定最终权限(mode&umask)。 umask代表文件在创建时需要去掉的存取…

8.12 矢量图层面要素单一符号使用十(箭头线渲染边界)

前言 本章介绍矢量图层线要素单一符号中箭头线渲染边界的使用说明:文章中的示例代码均来自开源项目qgis_cpp_api_apps 箭头线渲染边界(Outline: Arrow) Outline系列只画边界,不填充内容以protected_areas.shp为例,图…

Spring 动态增强逻辑执行分析

1、假如UserService中存在被增强的public 普通方法,那么spring ioc时就会创建对应的代理对象放置到容器中; 2、那么Controller中注入的userService就是代理对象; Service public class UserService {Transactionalpublic void f2(String us…

【训练篇】MLU370-M8 完成 qwen1.5-7b-chat-lora训练及推理

文章目录 前言一、平台环境配置二、环境 or 模型准备1.模型下载2.环境准备2.1 modelscope2.2 transformers2.3 accelerate2.4 deepspeed2.5 peft2.6 环境代码修改 3训练代码准备4 代码修改 三,训练后推理验证四.推理效果展示1.微调前2.微调后 前言 本期我们采用魔塔…

【雷达原理】雷达测角原理及实现方法

目录 一、雷达测角原理1.1 测角研究历史和现状1.2 测角方法总结1.3 3DFFT测角1.3.1 基本原理1.2.2 测角性能 二、MATLAB仿真案例参考文献 一、雷达测角原理 1.1 测角研究历史和现状 (1)早期采用窄波束对准目标,目标的角度对应于天线的角度读…

【高性能服务器】服务器概述

🔥博客主页: 我要成为C领域大神🎥系列专栏:【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 服务器概述 服…

[深入理解DDR] 总目录

依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解DDR》 蓝色的是传送门,点击链接即可到达指定文章。 图。 DDR 分类 导论 [RAM] DRAM 导论:DDR4 | DDR5 | LPDDR5 | GDRR6 | HBM 应运而生 运存与内存?内存与存…

Golang-GMP

GMP调度 golang-GMP语雀笔记整理 GMP调度设计目的,为何设计GMP?GMP的底层实现几个核心数据结构GMP调度流程 设计目的,为何设计GMP? 无论是多进程、多线程目的都是为了并发提高cpu的利用率,但多进程、多线程都存在局限性。比如多进程通过时…

第三方服务提供商的五大风险

亚马逊如何应对网络安全挑战 关键网络安全统计数据和趋势 移动优先世界中安全和隐私策略 当今数字时代网络安全的重要性 用户无法停止犯安全错误的 3 个原因 首席安全官可能过于依赖 EDR/XDR 防御 随着业务流程变得越来越复杂,公司开始转向第三方来提高其提供关…