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面试宝典》 

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

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

相关文章

算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)

💕"我们好像在池塘的水底,从一个月亮走向另一个月亮。"💕 作者:Mylvzi 文章主要内容:算法系列–动态规划–⼦数组、⼦串系列(数组中连续的⼀段)(1) 大家好,今天为大家带来的是算法系…

插槽和自定义命令

自定义指令 自定义的指令,定义好之后,在标签内使用,当执行new Vue去模板的时候,看到自定义指令,会将下面的函数,等到特定执行Vue实例阶段触发.模板渲染之后.当触发时的传参的参数的第一个是所写的对象的DOM对象,第二个是是包含指令的对象,对象value是指令赋值.当把指令写到标签…

qt生成word文档(wps),代码如下

这是我自己写的,建议往下滑,大佬写的很清楚,我的代码只是人家的一个摘抄部分 链接:https://pan.baidu.com/s/1MgG_dO8hCUi7ErQnOncNOg?pwd1234 提取码:1234使用方法: #include "ExportReport.h&qu…

6个步骤轻松实现 postman 接口压力测试(建议收藏)

这里讲是postman做接口并发测试,基础用法不做赘述 1、第一步接口可以通的情况下点击右上角save 2、将相应信息填入 3、如果是同一个接口修改不同的值如下图 4、点击左上角Runner 5、选择刚才所建接口集合、填入要执行次数 6、查看运行结果 总结: 感谢每…

24计算机考研调剂 | 【官方】湘潭大学

湘潭大学 考研调剂要求 招生专业: 调剂基本要求: (1)基本要求同《湘潭大学2024年硕士研究生复试录取工作方案》。 (2)初试成绩要求: 初试成绩各单科均须达到A类考生进入复试的初试成绩基本要…

代码随想录算法训练营第四十六天|139.单词拆分、56. 携带矿石资源(第八期模拟笔试)

139.单词拆分 刷题https://leetcode.cn/problems/word-break/description/文章讲解https://programmercarl.com/0139.%E5%8D%95%E8%AF%8D%E6%8B%86%E5%88%86.html视频讲解https://www.bilibili.com/video/BV1pd4y147Rh/?vd_sourceaf4853e80f89e28094a5fe1e220d9062 题解&…

微服务(基础篇-005-Gateway)

目录 Gateway介绍: 为什么需要网关(1) gateway快速入门(2) 断言工厂(3) 过滤器工厂(4) 过滤器工厂介绍及案例(4.1) 默认过滤器&#xff08…

公众号超牛鼻的爆文仿写机器人,原创三篇只需6分钟,篇篇是爆文基因

大家好,我是大胡子,专注于RPA提效​,今天就介绍一款公众号超牛鼻的爆文仿写机器人​。 和以前的公众号爆文机器人不太一样,以前的爆文机器人需要手动插入图片、添加封面、插入话题,然后今天这个机器人就完全解决这几个…

Redission 分布式锁原理分析

一、前言 我们先来说说分布式锁,为啥要有分布式锁呢? 像 JDK 提供的 synchronized、Lock 等实现锁不香吗?这是因为在单进程情况下,多个线程访问同一资源,可以使用 synchronized 和 Lock 实现;在多进程情况下&#xff…

美团面试一面凉经

1.自我介绍 2.科研项目提问 没咋准备,说的有点没逻辑 3.问论坛项目 为什么用Redis实现登录?能不能用其他方式实现? 1、Redis 具备高性能 假如用户第一次访问 MySQL 中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将…

Jmeter参数化定义和实现

Jmter参数化定义和实现 Jmter参数化参数化本质参数化实现用户定义变量用户参数CSV数据文件设置counter函数 Jmter参数化 参数化本质 使用参数的方式来替代脚本中的固定的测试数据 参数化实现 定义变量(最基础)文件定义的方式(所有测试数据都…

python 读取jpg图片

pillow读取图片 from PIL import Image import numpy as np img_path ./Training/meningioma/M546.jpg # 读取图片 image Image.open(img_path) width, height image.size print("图片的宽度为{},高度为{}".format(width,height)) print("图片的mode为{}&qu…

nginx--解决响应头带Set-Cookie导致的验证失败

解决响应头带Set-Cookie导致的验证失败 前言给nginx.conf 设置Secure配置完成后会发现cookie就不会发生变化了 前言 在用nginx做代理的时候,会发现nginx在访问不同ip请求的时候会带setCookie 导致后端就是放开cookie验证,在访问玩这个链接他更新了cooki…

nandgame中的计算机(Computer)

关卡说明的翻译: 计算机通过组合以下组件来构建一台计算机:一个控制单元 //应该是涵盖了ALU 存储器(RAM和寄存器) 程序存储单元(ROM) 一个计数器,用于跟踪当前指令地址(称为“程序计…

软件测试/测试开发丨Docker环境安装配置(Mac、Windows、Ubuntu)

macOS 安装 Docker brew cask install docker运行 Docker Ubuntu 安装 Docker # 更新 apt update # 安装依赖 apt install apt-transport-https ca-certificates curl software-properties-common -y # 添加 key curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/…

HTML基础:8个常见表单元素的详解

你好,我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端程序媛。 后台回复“前端工具”可免费获取开发工具,持续更新。 今天来说说 HTML 表单。它是用于收集用户输入信息的元素集合。例如文本框、单选按钮、复选框、下拉列表等。 用户经常填写的表…

【保姆级教程】YOLOv8自动数据标注

一、YOLOV8环境准备 1.1 下载安装最新的YOLOv8代码 仓库地址: https://github.com/ultralytics/ultralytics1.2 配置环境 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple1.3 安装labelme标注工具 pip install labelme二、半自动标注…

【操作系统】用户态和内核态

用户态和内核态指的是程序运行时处于状态,在不同时候处于的状态可能会不同。 操作系统为了保护自己而进行严格控制用户资源的访问,不需要外部资源的程序运行状态为用户态,反之需要内核操作资源时为内核态。 用户态到内核态时需要申请外部资源…

Beans模块之工厂模块BeanNameAware

博主介绍:✌全网粉丝5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…

【剑指offr--C/C++】JZ23 链表中环的入口结点 与哈希表

一、哈希表(unordered_set)知识点 unordered_set是一种无序的数据集合容器,元素和键同时存在,元素没有按任何特定的顺序排序,而是根据它们的散列(hash)值组织成桶,以允许直接通过值…