双重检验锁方式实现单例模式

单例模式(Singleton Pattern)是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。

单例模式有两种类型:

        1,饿汉式:就是说我很饿看到啥都吃,也就是在类加载的时候就创建给对象。

        2,懒汉式:不是很饿,当真正用到该对象的时候才进行创建。

单例模式注意

        1,单例类只能有一个实例

        2,单例类必须自己创建自己的唯一实例(对象不能new出来)

        3,单例类必须给所有其他对象提供自己创建好的实例

1,对应Java代码实现-饿汉式

//饿汉单例
public class HungrySingle {//构造器私有private HungrySingle(){}//创建自己的唯一实例private static final HungrySingle HUNGRY_SINGLE=new HungrySingle();//对外提供自己的这唯一实例private static HungrySingle getInstance(){return HUNGRY_SINGLE;}
}

2,对应Java代码实现-懒汉式

//懒汉单例
public class LazySingle {//构造器私有private LazySingle(){}private static LazySingle LAZY_SINGLE;private static LazySingle getInstance(){//当前实例没有被创建的时候才行创建if(LAZY_SINGLE==null){LAZY_SINGLE=new LazySingle();}return LAZY_SINGLE;}
}

3,双重检验锁方式实现单例模式   

上述的懒汉单例实现是不完美的,因为我们创建实例的时候需要先判断是否为空,单如果实在多线程环境下,同时判断这个实例对象为空于是就创建了不同的对象,测试如下:

package com.qmlx.springbootinit.Pattern;
//懒汉单例
public class LazySingle {//构造器私有private LazySingle(){System.out.println(Thread.currentThread().getName()+"线程创建了对象");}private static LazySingle LAZY_SINGLE;private static LazySingle getInstance(){//当前实例没有被创建的时候才行创建if(LAZY_SINGLE==null){LAZY_SINGLE=new LazySingle();}return LAZY_SINGLE;}public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{LazySingle instance = LazySingle.getInstance();System.out.println(instance);}).start();}}
}

代码执行结果如下:

 根据输出以及当前创建的对象,我们可以看到他创建了不同的对象,所以,为了解决这个方法,我们在创建对象的时候使用 synchronized关键字包裹  这样我们就能保证创建对象的操作式互斥的,从而保证对象的单例,这就是常说的双重检验锁方式实现单例模式

代码如下:

//懒汉单例
public class LazySingle {//构造器私有private LazySingle(){System.out.println(Thread.currentThread().getName()+"线程创建了对象");}private static LazySingle LAZY_SINGLE;private static LazySingle getInstance(){//当前实例没有被创建的时候才行创建if(LAZY_SINGLE==null){synchronized (LazySingle.class){if(LAZY_SINGLE==null){LAZY_SINGLE=new LazySingle();}}}return LAZY_SINGLE;}public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{LazySingle instance = LazySingle.getInstance();System.out.println(instance);}).start();}}}

但是他依旧存在问题,继续往下看。

LAZY_SINGLE=new LazySingle();

这段代码并不是原子性的,因为这段代码其实是分为三部分来执行的:

1,为LAZY_SINGLE分配内存空间

2,初始化LAZY_SINGLE,也就是执行构造方法去初始化这个对象

3,将LAZY_SINGLE指向分配的内存地址

正常步骤是1->2->3,但是JVM具有指令重排序的特性,在单线程下是不会存在问题的,但是在多线程下,会导致一个线程拿到还没有进行初始化的实例,例如线程1执行了1->3,然后线程二获取这个实例,发现不为空,拿到但是结果是没有初始化的。

4,如何防止指令重排序呢?

我们可以使用volatile关键字,他有两个关键作用:

1,保证线程间共享变量的可见性(防止了JIT对共享变量的优化),例如

你写的代码------------------>JIT优化之后的代码

 

所以,我们对变量添加volatile关键字就是告诉JIT编译器,我这个变量你不要优化。

2,防止指令重排序(JVM对程序执行中的优化)

所以我们对当前变量添加volatile关键字,当对这个变量进行读写操作的时候会通过擦汗如特定的内存屏障的方式来禁止指令重排序

具体如下(我的笔记,不知道可不可以帮助理解)

最终代码如下:

//懒汉单例
public class LazySingle {//构造器私有private LazySingle(){System.out.println(Thread.currentThread().getName()+"线程创建了对象");}private static volatile LazySingle LAZY_SINGLE;private static LazySingle getInstance(){//当前实例没有被创建的时候才行创建if(LAZY_SINGLE==null){synchronized (LazySingle.class){if(LAZY_SINGLE==null){LAZY_SINGLE=new LazySingle();}}}return LAZY_SINGLE;}}

 其实这种实现方式也不是完美的,因为Java中那可是存在反射的,他就可以破坏对象的单例!

具体如何???

等我深刻理解之后,在谈!!!!

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

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

相关文章

我是如何带团队从0到1做了AI中台

经历心得 我从18年初就开始带这小团队开始做项目&#xff0c;比如最初的数字广东的协同办公项目&#xff0c;以及粤信签小程序等&#xff0c;所以&#xff0c;在团队管理&#xff0c;人员安排&#xff0c;工作分工&#xff0c;项目拆解等方面都有一定的经验。 19年中旬&#…

WireShark对tcp通信数据的抓包

一、抓包准备工作 安装wireshark sudo apt update sudo apt install wireshark 运行 二、WireShark工具面板分析 上图中所显示的信息从上到下分布在 3 个面板中&#xff0c;每个面板包含的信息含义如下&#xff1a; Packet List 面板&#xff1a;显示 Wireshark 捕获到的所…

Qt QImageReader类介绍

1.简介 QImageReader 是用于读取图像文件的类。它提供了读取不同图像格式的功能&#xff0c;包括但不限于 PNG、JPEG、BMP 等。QImageReader 可以用于文件&#xff0c;也可以用于任何 QIODevice&#xff0c;如 QByteArray &#xff0c;这使得它非常灵活。 QImageReader 是一个…

【Docker】docker compose服务编排

docker compose 简介 Dockerfile模板文件可以定义一个单独的应用容器&#xff0c;如果需要定义多个容器就需要服务编排。 docker swarm&#xff08;管理跨节点&#xff09; Dockerfile可以让用户管理一个单独的应用容器&#xff1b;而Compose则允许用户在一个模板&#xff08…

商城数据库88张表结构完整示意图51~60(十三)

五十一&#xff1a; 五十二&#xff1a; 五十三&#xff1a; 五十四&#xff1a; 五十五&#xff1a; 五十六&#xff1a; 五十七&#xff1a; 五十八&#xff1a; 五十九&#xff1a; 六十&#xff1a;

GEE案例分析——2019年3月30日,四川省凉山州木里县雅砻江镇立尔村火灾面积分析(Sentinel-2和NBR)

简介 2019年3月30日18时许,四川省凉山州木里县雅砻江镇立尔村发生森林火灾,着火点在海拔3800米左右,地形复杂、坡陡谷深,交通、通讯不便。 1212据凉山州人民政府新闻办公室消息,火场在雅砻江边上,距木里县车程6到7个小时,火场平均海拔4000米,多个火点均位于悬崖上。森…

如何进行音频压缩大小?6个软件教你快速的压缩音频

如何进行音频压缩大小&#xff1f;6个软件教你快速的压缩音频 以下是六款常用的音频压缩软件&#xff0c;它们可以帮助您快速压缩音频文件大小&#xff1a; 迅捷视频剪辑软件&#xff1a; 这是一款非常实用的音频编辑软件&#xff0c;除了编辑音频外&#xff0c;它还提供了音…

C++使用json11开源库快速生成JSON格式的数据

在程序开发中&#xff0c;JSON格式的接口数据应用很广泛&#xff0c;C生态中有许多高效的JSON库&#xff0c;如nlohmann/json、RapidJSON、jsoncpp等&#xff0c;这些库提供了便捷的API来实现JSON数据的解析、生成、序列化和反序列化&#xff0c;简化了C程序对JSON数据的操作&a…

文件加密软件排行榜前四名(2024年4大好用的加密软件推荐)

说到文件加密&#xff0c;想必大家都很熟悉&#xff0c;文件加密已经普遍应用&#xff0c;文件加密是一种重要的安全措施&#xff0c;可以确保数据的机密性、完整性和可用性&#xff0c;降低因数据泄露或丢失带来的风险 。 下面小编给大家分享几款常用的加密软件&#xff0c;…

STM32单片机中C语言的一些隐藏bug

必须类型一致的判断才能正常 double a-0.4; if(a < -0.2){print("低电平"); }这段代码可能未必如你所愿的运行. < 小于号的判断一定要类型一致, 尤其是牵扯到双精度类型的判断… 一定要保证符号 两边的数据类型一致才有可能得到你想要的结果. 代码里 -0.4 默认…

贪心算法、Dijkstra和A*类路径搜索算法

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言系列文章目录前言1.贪心算法、Dijkstra和A*类路径搜索算法(1)greedy best frist search贪心算法(仅仅考虑启发式代价)1.核心思想2.构造启发式猜…

权益商城系统源码 现支持多种支付方式

简介&#xff1a; 权益商城系统源码&#xff0c;支持多种支付方式&#xff0c;后台商品管理&#xff0c;订单管理&#xff0c;串货管理&#xff0c;分站管理&#xff0c;会员列表&#xff0c;分销日志&#xff0c;应用配置。 上传到服务器&#xff0c;修改数据库信息&#xff…

C++例题:大数运算---字符串相加(使用数字字符串来模拟竖式计算)

1.代码速览 class Solution2 { public:string addStrings(string num1, string num2){//end1和end1是下标int end1 num1.size() - 1;int end2 num2.size() - 1;string str;//下标(指针)从后向前走,走到头才可以结束,所以是end>0int next 0;while (end1 > 0 || end2 &…

2024icpc武汉站邀请赛F.Custom-Made Clothes(交互题)

2024 i c p c 武汉站邀请赛 F . C u s t o m − M a d e C l o t h e s \Huge{2024icpc武汉站邀请赛F.Custom-Made Clothes} 2024icpc武汉站邀请赛F.Custom−MadeClothes 文章目录 题意思路标程 题目链接&#xff1a;F. Custom-Made Clothes 题意 本题是一道交互题。 给出一个…

百日训练(第四周 , 第一天)

放了一个五一假期&#xff0c;玩了五天&#xff0c;没有刷任何题&#xff0c;今天做一个恢复训练 洛谷 —— 奶酪 P3958 [NOIP2017 提高组] 奶酪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 不难发现&#xff0c;这题可以用并查集&#xff0c;那么就有两个问题需要解决 …

拓扑是什么意思

拓扑学&#xff0c;有时候被称为“橡胶片几何学”&#xff0c;它是研究空间形状在连续变形下的性质的数学分支。这种变形包括拉伸、压缩、扭曲&#xff0c;但不包括撕裂或粘合。 一个经典的拓扑问题就是“环面和咖啡杯”的问题。在拓扑学中&#xff0c;一个环面&#xff08;就…

Swift 周报 第五十期

文章目录 前言新闻和社区WWDC24&#xff1a;6 月 10 日至 14 日 (太平洋时间)苹果“内忧外患”&#xff0c;库克中国求援苹果被起诉&#xff01;市值一夜蒸发8000亿元 提案通过的提案正在审查的提案拒绝的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组自主…

unity车辆碰撞检测

在Unity中根据车辆碰撞检测去调度车辆集群行驶可以通过以下方法实现&#xff1a; 添加碰撞检测组件&#xff1a;在每辆车辆上添加Collider组件和Rigidbody组件&#xff0c;以便进行碰撞检测和物理模拟。 设定车辆行驶轨迹&#xff1a;为每辆车辆设定行驶轨迹或目标点&#xff…

八股spring+springboot+springMVC+Mybatis(一)

目录 1、面试官&#xff1a;Spring框架中的单例bean是线程安全的吗&#xff1f; 2、面试官&#xff1a;什么是AOP 3、面试官&#xff1a;你们项目中有没有使用到AOP 4、面试官&#xff1a;Spring中的事务是如何实现的 5、面试官&#xff1a;Spring中事务失效的场景有哪些 6、面…

行业推荐:数据防泄漏软件首先解决方案

随着信息时代的快速发展&#xff0c;数据安全已成为企业经营的关键之一。然而&#xff0c;数据泄漏事件时有发生&#xff0c;不仅可能导致巨大的经济损失&#xff0c;更会损害企业的声誉和客户信任。 为了帮助企业有效地保护数据安全&#xff0c;Ping32 数据防泄漏系统应运而生…