【JavaEE初阶】懒汉模式与饿汉模式及指令重排序问题

news2024/9/24 7:16:35

目录

📕 单例模式

🌳 饿汉模式

🚩 线程安全

🎍 懒汉模式

🚩 懒汉模式-单线程版

🚩 懒汉模式-多线程版

🎄 指令重排序


📕 单例模式

单例模式是一种经典的设计模式,是校招中最常考的设计模式之一.

那么啥是设计模式呢?

  • 设计模式好比象棋中的 “棋谱”. 红方当头炮, 黑方马来跳. 针对红方的一些走法, 黑方应招的时候有一些固定的套路. 按照套路来走局势就不会吃亏.
  • 软件开发中也有很多常见的 “问题场景”. 针对这些问题场景, 大佬们总结出了一些固定的套路. 按照这个套路来实现代码, 也不会吃亏.

那么什么是单例模式呢?

  • 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
  • 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
  • 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。

注意:

  1. 单例类只能有一个实例。

  2. 单例类必须自己创建自己的唯一实例。

  3. 单例类必须给所有其他对象提供这一实例

单例模式具体的实现方式, 又分成 “饿汉” 和 “懒汉” 两种,掌握这两种应付面试+日常开发完全足够

🌳 饿汉模式

饿汉模式,就是它很饿,它的对象早早的就创建好了

由于是 static 修饰的,所以由 static 修饰的成员初始化时机是在类加载的时候,类具体啥时候加载,后面讲到JVM的时候再细说,可简单的认为就是在JVM一启动的时候就立即加载了(其实有变数)。

现在呢我们是有一个private这样的成员,光一个private成员还不够,要写一个public这样的方法供其他代码进行使用。

后序呢,在代码里面要想用到这个类的实例,就直接通过 getinstance 来获取,而不是重新去new

接下来,上述代码是已经把唯一实例准备好了,万一其他代码又new了这个类的实例怎么办,所以我们就需要禁止外部代码来创建该类的实例,在Singleton类里面在创建一个构造方法即可,里面可以什么都不写,但是必须要由private修饰(核心)。

在main方法调用:

尝试在main方法中new,就会编译出错:  提示说该方法是私有的,不能访问

注意:

  • 优点:没有加锁,执行效率会提高。

  • 缺点:类加载时就初始化,浪费内存

🚩 线程安全

🎍 懒汉模式

🚩 懒汉模式-单线程版

代码:

饿汉模式的代码突出的就是一个急切,只要程序启动就创建出实例,而懒汉模式是在第一次调用getinstance的时候创建实例,啥时候调用就啥时候创建,如果不调用就不创建。

main方法调用:还是一样,不管调用几次都是同一个实例

尝试去new,也会出现语法错误:

线程不安全:

🚩 懒汉模式-多线程版

上面的懒汉模式的实现是线程不安全的.

  • 线程安全问题发生在首次创建实例时.如果在多个线程中同时调用getInstance方法,就可能导致创建出多个实例.
  • 一旦实例已经创建好了,后面再多线程环境调用getInstance就不再有线程安全问题了(不再修改 instance 了)

我们可以加上 synchronized 可以改善这里的线程安全问题

代码:

注意:锁这个东西不是说加了一定安全,也不是不加一定不安全,这里仍然使存在线程安全问题的

把加锁操作放到 if 外面,就是把 if 和 new 打包成一个原子操作:

问题:

只要在加锁之前再次判断 ->if ( instance == null ) 即可,就能使这个代码线程安全即效率不受影响

通过双重 if 避免了不可重复读负面影响,避免了重复创建对象。

注意:之前谈到的 volatile 的优化问题,不是100%触发的,可能触发,可能不触发,上述代码考虑的是不触发优化的情况,如果触发优化的情况,需要再来一手 volatile。避免出现优化情况下的内存可见性问题,确保说第一个线程的修改操作一定会被后序线程读到。

🎄 指令重排序

上述讲到给变量加上 volatile 是因为涉及到内存可见性问题,另一方面加上 volatile 也能够解决指令重排序引起的线程安全问题。

指令重排序呢也是编译器的一种优化策略。

注意:编译器优化有多种策略,把读内存优化到读寄存器,指令重排序,循环展开,条件分支预测......这些都是优化策略,也是属于比较垂直的领域,对于大部分程序员不需要知道,属于专门负责开发编译器/开发操作系统内核一小部分人研究。

那对于上篇文章写的懒汉模式的代码来说,如果不给这里的 instance 加上 volatile 的话,此时是有可能在多线程环境下出现指令重排序引起的线程安全问题。

那具体是怎么引起的 ?

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

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

相关文章

Python | Leetcode Python题解之第312题戳气球

题目: 题解: class Solution:def maxCoins(self, nums: List[int]) -> int:n len(nums)rec [[0] * (n 2) for _ in range(n 2)]val [1] nums [1]for i in range(n - 1, -1, -1):for j in range(i 2, n 2):for k in range(i 1, j):total v…

文档编辑协作神器,全方位解决方案,灵活部署赋能个人与企业-onlyoffice

文章目录 1. 引言2. 免费畅享,个人的编辑利器2.1 PDF直接修改功能2.2 插件支持,应对多种工作场景2.3 AI助手智慧办公 3. 私有部署,开发者的自定义编辑器3.1 开发者版本介绍3.2 私有部署,解决数据安全问题3.3 实用功能丰富&#xf…

基于SpringBoot+Vue的流浪猫狗救助救援网站(带1w+文档)

基于SpringBootVue的流浪猫狗救助救援网站(带1w文档) 基于SpringBootVue的流浪猫狗救助救援网站(带1w文档) 该流浪猫狗救助救援网站在Windows平台下完成开发,采用java编程语言开发,将应用程序部署于Tomcat上,加之MySQL接口来实现交互式响应服…

LKEB-4030电阻器LKEB4030模块可议价

LKEB-4030电阻器LKEB4030模块可议价 LKEB-4030电阻器LKEB4030模块可议价 LKEB-4030电阻器LKEB4030模块可议价 LKEB-4030电阻器LKEB4030模块说明书 LKEB-4030电阻器LKEB4030模块接线图 LKEB-4030电阻器LKEB4030模块线路图 LKEB-4030电阻器(Resistor&#xff09…

新手如何参加护网行动?一篇带你零基础入门到精通

前言 1、什么是护网行动 “护网行动”是指国家组织的网络安全防护演练行动。 护网行动通常由国家相关部门组织,旨在模拟真实的网络攻击情况,检验和提升关键信息基础设施、重要信息系统和大数据的安全防护能力。 在护网行动中,会有专业的攻…

基于微信小程序的搬家服务系统(源码+lw+部署文档+讲解等)

博主介绍:✌全网粉丝10W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 涉及技术栈:SpringBoot、Vue、SSM、H…

SEO域名篇—如何选择一个好域名

SEO 域名选择误区 很多做站的大佬都告诉新入行的SEO优化员,选择域名一定要选择老域名,这里也是一个误区,很多新手在听了大佬的话后去就选择一些5年-15年的老域名直接做站,不去查查这个域名是否被360、QQ、微信等等一切搜索引擎拦…

Unity | Shader基础知识(第二十集:应用-简易流光、LOD)

目录 一、前言 二、LOD 1.什么是LOD 2.代码如何调节LOD 三、流光 1.资源准备 2.uv移动 3.获取图片中的uv 4.改变uv去取流光的颜色(时间的应用) 5.图片叠加 6.透明图片的叠加 四、纯净代码 五、作者的碎碎念 一、前言 有小伙伴问&#xf…

使用腾讯云域名解析实现网站重定向

前言 最近,在CSDN平台上我写了一系列博客,希望能与同学分享一些技术心得。然而,每当需要向他人推荐我的博客时,那串复杂且缺乏规律的CSDN博客首页域名总让我感到不便。这让我开始思考,如果能将这一域名替换为一个既个…

技术速递|VS Code Java 7月更新 - Gradle 支持增强!用户体验改进与 Spring 新功能

作者:Nick Zhu 排版:Alan Wang 大家好,欢迎来到 Visual Studio Code 7月份的 Java 更新!本博客将覆盖最新的 Gradle 功能增强、用户体验改进以及新的 Spring 功能,让我们开始吧! Gradle 功能增强 支持 Gr…

算法强训day19

一、小易的升级之路 链接&#xff1a;小易的升级之路_牛客题霸_牛客网 简单题 #include<iostream> using namespace std; long long gcd(long long m, long long x) {long long n ;while(x>0){n m % x;m x;x n;}return m; } int main() {int n;long long m;cin &…

文件上传漏洞--之upload-labs靶场(第6-10关)专栏更新ing......

注意&#xff1a; 为避免执行之前关卡的上传了的php文件代码&#xff0c;可以将upload文件夹下的文件清空 第六关&#xff1a; 第一步&#xff1a;查看源码 对比前面的几个关卡&#xff0c;里面没有文件去空格语句&#xff0c;可以使用后缀名加空格绕过 第二步&#xff1a;…

Python初学者必须掌握的基础知识点

Python初学者必须掌握的基础知识点包括数据类型与变量、控制结构&#xff08;条件语句和循环语句&#xff09;、基本数据结构&#xff08;列表、元组、字典、集合&#xff09;、函数与模块、以及字符串处理等。以下是对这些基础知识点及其对应代码的详细介绍&#xff1a; 1. …

Git常用命

转自&#xff1a;https://blog.csdn.net/ahjxhy2010/article/details/80047553 1.查看某个文件或目录的修改历史 git log filename #查看fileName相关的commit记录 git log -p filenam # 显示每次提交的diff#只看某次提交中的某个文件变化&#xff0c;commit-id  文件名…

【视频讲解】CatBoost、LightGBM和随机森林的海域气田开发特征分类研究

原文链接&#xff1a;https://tecdat.cn/?p37208 原文出处&#xff1a;拓端数据部落公众号 分析师&#xff1a;Changlin Li 本文将通过视频讲解&#xff0c;展示如何用CatBoost、LightGBM和随机森林的海域气田开发特征智能分类&#xff0c;并结合一个python分类预测职员离…

虚拟网卡添加ip

1.虚拟机网卡添加 1.进入虚拟机设置添加网卡即网络适配器 2.配置文件修改 1.查看网卡是否添加成功 ip ad ifconfig 其中ens161就是我们新添加的设备同时这个ens161也是我们硬件名字 2.进入系统配置文件 cd /etc/sysconfig/network-scripts/#配置文件目录[rootlocalhost ne…

小程序~~4(npm支持+分包加载+开放功能)

目录 1.npm支持 自定构建npm vant组件库的使用 vant app组件样式覆盖 2.分包加载 介绍 分包加载及打包引用原则 独立分包的配置 分包预下载 3.开放能力 获取微信头像 获取微信昵称 转发功能 分享到朋友圈 手机号验证组件 客服功能 框架接口-getApp() 页面间通…

使用hutool工具将数字类型集合转换为字符串数组,long类型集合转字符串集合或数组相互转换

1.导入hutool的maven依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency>2.直接复制代码运行 import cn.hutool.core.convert.Convert; import java.…

C语言:指针(2)

一.数组名 在了解数组名前我们先看一段代码 int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 根据我们上一篇学习的知识&#xff0c;我们知道&arr[0]是数组第一个元素的地址&#xff0c;这时我们再看另一段代码的运行结果。 #include <stdio.h> int ma…

U盘文件或目录损坏的应对之策:从绝望到希望

遭遇困境&#xff1a;U盘文件或目录的隐形危机 在日常的数字存储与传输中&#xff0c;U盘以其便携性和高容量成为了我们不可或缺的工具。然而&#xff0c;当U盘中的文件或目录突然损坏且无法读取时&#xff0c;这份便捷瞬间化为了困扰。面对屏幕上冰冷的错误提示&#xff0c;用…