Spring常用设计模式-实战篇之单例模式

  实现案例,饿汉式 + Double-Check机制 + synchronized锁

/**
 * 以饿汉式为例
 * 使用Double-Check保证线程安全
 */
public class Singleton {

    // 使用volatile保证多线程同一属性的可见性和指令重排序
    private static volatile Singleton instance;

    public static Singleton getInstance() {
        // 第一次check
        if (instance == null) {
            synchronized (Singleton.class) {
                // 第二次check
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

}

1、两次check的作用

第一次check:为了提高效率,假如我的instance已经不为null了,就没必要进入同步代码块了;

第二次check:因为在没有获取实例之前,即instance为null之前,可能有多个线程进入了第一个if之内,这个时候为了防止创建多个实例,使用同步代码块,一个线程一个线程进入,当Instance不为null时,才new对象,保证了对象实例只被 new 一次,即保证单例模式。

2、为什么使用了synchonized同步还要加volatile关键字

 首先,synchonized可以保证原子性和可见性,但是他保证不了指令重排序这种情况。

 那指令重排序存在什么问题呢?

当线程A和B分别执行到以上位置时,

 1)对于  instance = new Singleton(); 这个操作,其实分为三个步骤:

  1. JVM为对象分配一块内存;
  2. 在内存上为对象进行初始化;
  3. 将内存的地址赋值给singleton变量;

这样是没有问题的,因为只有把内存地址赋值给singleton变量以后,instance才不等于null,而赋值之前就已经初始化了,所以线程B不会出现误判的情况;

2)但是假如不使用volatile,编译器可能会优化,将2,3替换位置,也就是:

  1. JVM为对象分配一块内存;
  2. 将内存的地址赋值给singleton变量;
  3. 在内存上为对象进行初始化;

这样就可能会出现问题了,场景如下:

        当A线程赋值了以后,还没来得及初始化呢,这个时候线程B刚好判断instance == null,返回false,直接return instance了,但此时这个instance实际上是还没初始化的bean,这样就有问题了。

总结

  1. 懒汉式是线程不安全的,可以通过synchonized进行加锁,保证它的一个线程安全性;
  2. 如果你想提高它的效率,可以使用Double-Check这种机制,让它存在实例以后无需再去竞争锁,在外层 if 即可直接判断;
  3. 当你使用Double-Check这种机制的时候,请注意加上volatile关键字,防止优化器指令重排序带来的影响。

ps:以下是我整理的java面试资料,感兴趣的可以看看。最后,创作不易,觉得写得不错的可以点点关注!

链接:https://www.yuque.com/u39298356/uu4hxh?# 《Java面试宝典》 

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

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

相关文章

VUE中添加视频播放功能

转载https://www.cnblogs.com/gg-qq/p/10782848.html 常见错误 vue-video-player下载后‘vue-video-player/src/custom-theme.css‘找不到 解决方法 卸载原来的video-play版本 降低原来的版本 方法一 npm install vue-video-player5.0.1 --save 方法二 或者是在pack.json中直…

huggingface的transformers训练gpt

目录 1.原理 2.安装 3.运行 ​编辑 4.数据集 ​编辑 4.代码 4.1 model init​编辑 forward: 总结: 关于loss和因果语言模型: ​编辑 交叉熵:​编辑 记录一下transformers库训练gpt的过程。 transformers/examples/…

使用 Amazon SageMaker 微调 Llama 2 模型

本篇文章主要介绍如何使用 Amazon SageMaker 进行 Llama 2 模型微调的示例。 这个示例主要包括: Llama 2 总体介绍Llama 2 微调介绍Llama 2 环境设置Llama 2 微调训练 前言 随着生成式 AI 的热度逐渐升高,国内外各种基座大语言竞相出炉,在其基础上衍生出…

MIT的研究人员最近开发了一种名为“FeatUp”的新算法,这一突破性技术为计算机视觉领域带来了高分辨率的洞察力

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

vuecli创建vue3项目

第一步: 在文件夹中输入 vue create xxx 第二步: 勾选下面带有*号的,经验最好把Linter/Formatter勾掉,不然会出现eslint报错 第三步: 选择3.x 第四步: 意思为是否用history模式来创建路由&#xff0…

mineadmin前端安装启动

在上一篇文章中, 我们已经搭建好了后端环境并启动 mineadmin 快速安装部署(docker环境) 一、下载前端项目 1、在搭建后端时候,使用php bin/hyperf.php mine:install 的时候,有一个步骤是安装前端项目的。安装目录为&a…

【有源码】buildroot根文件系统编译和常见问题

前言 编译好的含有QT5等工具包的buildroot根文件 仓库:https://gitee.com/wangyoujie11/atkboard_-linux_-driver 编译过程如下 1.下载源码,解压tar -vxjf xxx.tar.bz2 https://buildroot.org/ 这里以如下版本实验 2.在解压之后的buildroot-2019.02.…

智慧公厕的系统构成与功能解析

智慧公厕系统是通过传感器和云平台相结合的创新技术,旨在提供更好的公厕管理与服务。智慧公厕从系统的构成来看,主要分为感知层(数据收集)、传输层(数据传输)、平台层(数据处理)和应…

【vue-小知识】var、let 和 const之间的区别

文章目录 结论1、重复定义变量名var:允许重复定义变量名let和const:不可以重复定义变量名 2、修改值var:允许修改值let:允许修改值const:不允许修改值,会报错 3、变量提升var : 支持变量提升let和const&…

查看VMWare ESXi 6.5/6.7服务器上 GPU直通的状态

VMWare ESXi 6.5/6.7服务器状态 查看配置参数

Google的MELON: 通过未定位图像重建精确3D模型的突破性算法

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

OFC2023活动剪影

马上就要OFC 2024了,应该有些新图可以发一发了 先发点老图,丢在这里,怕下次不知道去哪里找 以上是以太网联盟Ethernet Alliance 在OFC2023上展示的一个演示机柜 以下是我们参与OFC2023的剪影,除了参与EA的演示,还有独…

从错误中进行上下文学习

1、写作动机: 在上下文学习中,也称为少样本提示(ICL),一直是调整LLM适应下游任务的标准方法,通过从少量输入-输出示例中学习。然而,所有基于ICL的方法都只从正确的输入-输出对中学习。 2、主要…

京东云开发者:DDD 学习与感悟 —— 向屎山冲锋

原文地址:https://mp.weixin.qq.com/s/Hvq1ttBopbxypatVcKcLiA 软件系统是通过软件开发来解决某一个业务领域或问题单元而产生的一个交付物。而通过软件设计可以帮助我们开发出更加健壮的软件系统。因此,软件设计是从业务领域到软件开发之间的桥梁。而DDD是软件设计…

基于ARM 的Linux系统的交叉编译

返回:OpenCV系列文章目录(持续更新中......) 上一篇:在 MacOS 中安装 下一篇:MultiArch与Ubuntu/Debian 的交叉编译 警告 本教程可以包含过时的信息。 此步骤已在 Ubuntu Linux 12.04 上进行了测试,但应…

JAVA 获取系统当前时间、时间格式互相转化工具类,2024百度Java岗面试真题收录解析

DateTimeFormatter ftf DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”); LocalDateTime parse LocalDateTime.parse(strTime, ftf); return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } //通过LocalDateTime获取当…

【论文精读】OTA: Optimal Transport Assignment for Object Detection(物体探测的最优传输分配)

OTA最优传输 🚀🚀🚀摘要一、1️⃣ Introduction---介绍二、2️⃣Related Work---相关工作2.1 🎓 Fixed Label Assignment--静态标签分配2.2 ✨Dynamic Label Assignment--动态标签分配 三、3️⃣Method---论文方法3.1 &#x1f39…

CPP容器vector和list,priority_queue定义比较器

#include <iostream> #include <bits/stdc.h> using namespace std; struct VecCmp{bool operator()(int& a,int& b){return a>b;/*** 对于vector和list容器&#xff0c;这里写了&#xff1e;就是从大到小* 对于priority_queue容器&#xff0c;这里写…

Linux第82步_“gpio子系统”下的使用KEY开关灯

使用新字符设备驱动的一般模板和“gpio子系统”&#xff0c;以及设备树&#xff0c;驱动KEY和LED。 1、在stm32mp157d-atk.dts文件中添加“gpio_led”和“key0”节点 打开虚拟机上“VSCode”&#xff0c;点击“文件”&#xff0c;点击“打开文件夹”&#xff0c;点击“zgq”&…

QChart/QChartView—绘制多组柱状图

void Widget::initChartBar() {// 创建柱状图QChart* pChart new QtCharts::QChart();pChart->setTitle("Multiple Bar Chart with Dates");// 创建柱状图序列QBarSeries* pSeries new QtCharts::QBarSeries();// 启用柱状图标签显示,可以把数据显示柱状图上pSe…
最新文章