设计模式(二)-创建者模式(1)-单例模式

概述

为何需要单例模式(Singleton Pattern)?

在程序运行当中,我们只希望一个类只能创建一个对象,在多个地方可以公用这个唯一的对象。

特点: 必须保证类只能创建一个对象。

单例模式可分为:饿汉式和懒汉式

1)饿汉式
特点: 类加载时(程序一开始运行时),该单例对象就被创建。
(所谓饿,饿肚子就马上干饭,所以程序一运行,就会被创建。)
优点: 没有出现线程安全问题。
缺点: 浪费内存空间。如果创建一个非常大的实例,到程序结束都没有被使用到,就浪费了资源。同时也会导致程序运行很慢,尤其在程序启动的时候。

2)懒汉式:
特点: 类加载不会创建单例对象,而是在程序运行中首次使用到单例对象时,才会开始被创建。
(所谓懒,不需要时不会创建。需要时才去检查有没有实例化,如果有就会返回实例对象,没有则会创建一个。)
缺点: 线程不安全。在程序运行中,可能会存在多个线程轮询干活。如果有多个线程同时判断是否有单例对象,如果都判断没有,就同时创建了多个对象。

1、饿汉式(静态变量)
    public class Singleton{private Singleton() { }private static Singleton instance = new Singleton();public static Singleton getInstance(){ return instance;}}
2、饿汉式(静态代码块)
//通过静态代码块(C# 不支持)public class Singleton{private Singleton() { }private static Singleton instance;static { instance = new Singleton();public static Singleton geetInstance() { return instance; }}
3、懒汉式(线程不安全)
public class Singleeton{private Singleeton() { }private static Singleeton instance;public static Singleeton getInstance{get{if (instance == null){instance = new Singleeton();}return instance;}}

缺点: 如果有多个线程同时访问单例对象,会可能存在上一个线程还没有创建好对象时,而下一个线程因为判断该对象为空就重复创建一个对象。

4、懒汉式(线程安全)
   public class Singleeton{private Singleeton() { }private static Singleeton instance;private static object lockobj = new object();public static Singleeton getInstance(){//加锁的作用:保证创建唯一的单例对象//缺点:当单例对象创建好后,仍会导致其他线程进行等待抢锁,而不是直接返回该对象。lock(lockobj){if (instance == null){instance = new Singleeton();}}return instance;}}

优点: 解决了多个线程重复创建对象的问题。因为在单例对象判断是否存在前加了把锁,说明需要等待上一个线程创建好单例对象了,才能把执行权分配给下一个线程去执行 if 代码块。

缺点: 影响性能。如果单例对象已经创建好,其他线程为了使用该单例对象时,仍然会进行排队抢锁,从而增加了抢锁的时间,而不是直接返回该对象。

5、懒汉式(双重检查锁)
    public class Singleeton{private Singleeton() { }private static Singleeton instance;private static object lockobj = new object();public static Singleeton getInstance(){//如果存在单例对象就直接返回该对象,避免浪费排队强锁的时间。if (instance == null){lock (lockobj){if (instance == null){instance = new Singleeton();}}}return instance;}}

还存在缺点: 在代码执行过程中,会存在指令的执行顺序问题。即指令的执行顺序并不一定会按照我们编写的顺序执行。也就说,系统可能会存在对指令重排序问题。所以这会导致程序不一定能及时拿到单例对象变量(instance)的最新值。这样即使能拿到不为空的 instance 变量,也不确保这个变量是否完全被创建好。

6、懒汉式(双重检查锁改进)
 public class Singleeton{private Singleeton() { }//改进:在双重检查锁的代码中,只在 instance 变量中加了修饰符 volatile.private static volatile Singleeton instance;private static object lockobj = new object();//....}

为何 instance 变量 需要使用 volatile 修饰符?

如果 instance 变量去掉修饰符 volatile 的话,就不能保证该代码执行的正确性。因为instance = new SIngleton();这行代码并不是原子操作。(原子操作:不会被线程调度机制打断的操作,中间的执行不会切换到另一个线程来操作,也就是new 单例变量和单例对象具体创建的过程并不是由同一个线程执行的)。

打个比方:骑手送外卖。他一般工作的顺序就是送餐到达地点后,然后联系顾客,最后把餐丢到顾客嘴里。但是有时候呢,他可能因为其他事情如赶时间等原因,还没到送达点,就先联系顾客说外卖到了。结果就是顾客开门没看到外卖,就一直张着嘴,结果吃的是西北风。
如果顾客在APP上设置了通知功能,当骑手真的到送达点了就马上通知顾客。

这个例子,就相当于:

  • 多线程:顾客拿餐、骑手送外卖过程、外卖中途有其他事情等。
  • instance = new instance():顾客用餐。
  • 创建Instance:骑手送餐、联系顾客,送达这一过程。
  • 指令重排序:骑手中途先联系顾客,再到送达点。
  • volatile:一旦骑手到了送达点,APP就会马上通知顾客。否则,就继续等待用餐。

初始化对象的顺序问题
Java 有JVM,同样的C#也会存在相似的运行环境,即 CLR。
在运行环境中,对类对象创建时会存在三个阶段执行:

  • 1)为变量分配内存
  • 2)初始化变量
  • 3)将变量指向分配的内存空间

如果系统存在重排序,就可能会出现执行顺序问题。也就是说,系统可能存在先执行第三步后执行第二步,也可能会正常按顺序执行。前者的执行顺序,会导致变量还没有初始化完成,其他线程就已经判断了该变量值不为空,然后返回一个没有初始化完成的单例对象。

volatile的作用
(1)保证并发编程的可见性(不保证原子性)
单线程时重排序无影响,但是多线程就有可能会读取到脏数据,这就需要用 volatile。使用 volatile 修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新值。

(2)禁止指令重排序
用 volatile 修饰保证执行顺序。

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

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

相关文章

使用ssh在本地环境(Windows)连接虚拟机以及其中的docker容器

配置虚拟机防火墙 防火墙的一系列操作需要root权限,默认是没有root密码的,所以首先需要设置root密码: sudo passwd root按提示完成root密码设置 切换到root账户 su root启用22端口并重启防火墙 firewall-cmd --permanent --add-port22/tc…

【NI-RIO入门】CompactRIO介绍及环境安装

CompactRIO是什么? CompactRIO系统提供了高处理性能、传感器专用I/O和紧密集成的软件工具,使其成为工业物联网、监测和控制应用的理想之选。实时处理器提供可靠,可预测的行为,而FPGA在需要高速逻辑和精确定时的较小任务上表现出色…

Microsoft Visual Studio 2019下载及安装流程记录

第一周任务: 1.笔记本上安装vc2019的环境 2.再把OpenCV安装上 3.根据网上的教程,试着写几个opencv的程序 一、安装Visual Studio 2019社区版 首先先完成安装vc2019的环境, 因为: Microsoft Visual C是用于C编程的工具集合&am…

机器学习笔记 - Ocr识别中的CTC算法原理概述

一、文字识别 在文本检测步骤中,分割出了文本区域。现在需要识别这些片段中存在哪些文本。 机器学习笔记 - Ocr识别中的文本检测EAST网络概述-CSDN博客文章浏览阅读300次。在 EAST 网络的这个分支中,它合并了 VGG16 网络不同层的特征输出。现在,该层之后的特征大小将等于 p…

什么是一阶逻辑?

一阶逻辑(FOL)是指句子或陈述的谓词只能指单个主语Subject的逻辑。 一阶逻辑也称为谓词逻辑或一阶谓词逻辑,它不但能以更简便的方式表达对象信息,还能表达这些对象之间的关系。 一阶逻辑(像自然语言一样)…

matlab 坡度滤波算法地面分割

目录 一、算法原理1、实现流程2、参考文献二、代码实现三、结果展示四、测试数据一、算法原理 1、实现流程 1、格网示意图 2、计算格网行列数 公式中的特殊符号为向上取整,

el-tree结合el-switch实现状态切换

<template><div><el-col :span"24"><el-card class"tree-card"><div class"sketch_content selectFile"><span class"span_title">组织列表 </span><div style"display: flex; jus…

【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷D

1、有一袋巧克力棒被摔倒了地上&#xff0c;其中只剩三分之一是完整的&#xff0c;而其它的每一根都断成两段。在这袋内所有的巧克力棒&#xff08;包括完整与断裂的&#xff09;中&#xff0c;请问长度不小于原来整根巧克力棒一半的根数至少占所有的根数的几分之几&#xff08…

《崩坏:星穹铁道》1.5仙舟罗浮-绥园全宝箱攻略

大家好&#xff0c;我是闲游盒小盒子&#xff0c;本篇来说下崩铁1.5版本仙舟罗浮-绥园的全宝箱攻略&#xff0c;共有19个宝箱加1个扑满&#xff1b;做完间章可获取前14个普通宝箱加2个精英怪宝箱&#xff0c;以及1个扑满&#xff1b;完成《狐斋志异》全任务可获得另外3个宝箱。…

数据结构 栈Stack的理解与C语言实现

栈&#xff0c;通俗的理解是叠盘子&#xff0c;如我们吃完饭洗碗洗盘子时&#xff0c;设盘子大小形状一样的&#xff0c;那么可以顺利的叠成一竖&#xff0c;每次我们洗好一个就叠在最上面push top&#xff0c;需要取用时候为了方便也是取最上面pop top&#xff0c;当然我们可以…

壹基金宣传进瑞金河背街社区 安全家园项目防灾减灾深入人心

11月16日下午&#xff0c;瑞金赋能公益、蓝天救援队等联合象湖镇河背街社区开展家庭安全计划社区活动包挑战赛活动暨壹基金安全家园项目防灾减灾宣传社区行活动。活动得到了救助儿童会北京代表处、壹基金、艾特公益、益心益意公益的指导&#xff0c;得到了阿里巴巴公益平台广大…

读像火箭科学家一样思考笔记04_第一性原理(下)

1. 来自无形规则的阻力 1.1. 无形规则 1.1.1. 僵化成规则的不必要习惯和行为 1.1.2. 不像有形的书面规则 1.1.2.1. 书面规则出现在标准操作流程中&#xff0c;可以修改或删除 1.1.3. 成文的规则可能会抗拒变革&#xff0c;但无形规则却更加顽固 1.1.4. 我们为强加在自己身…

【Q2—30min】

1.socket服务端创建过程 socket是应用层与TCP/IP协议族通信的中间软件抽象层&#xff0c;它是一组接口。在设计模式中&#xff0c;Socket其实就是一个门面模式&#xff0c;它把复杂的TCP/IP协议族隐藏在Socket接口后面&#xff0c;对用户来说&#xff0c;一组简单的接口就是全部…

从0开始学习JavaScript--JavaScript使用Promise

JavaScript中的异步编程一直是开发中的重要话题。传统的回调函数带来了回调地狱和代码可读性的问题。为了解决这些问题&#xff0c;ES6引入了Promise&#xff0c;一种更现代、更灵活的异步编程解决方案。本文将深入探讨JavaScript中如何使用Promise&#xff0c;通过丰富的示例代…

spider 网页爬虫中的 AWS 实例数据获取问题及解决方案

前言 AAWS实例数据对于自动化任务、监控、日志记录和资源管理非常重要。开发人员和运维人员可以通过AWS提供的API和控制台访问和管理这些数据&#xff0c;以便更好地管理和维护他们在AWS云上运行的实例。然而&#xff0c;在使用 spider 框架进行网页爬取时&#xff0c;我们常常…

.Net6 部署到IIS示例

基于FastEndpoints.Net6 框架部署到IIS 环境下载与安装IIS启用与配置访问网站 环境下载与安装 首先下载环境安装程序&#xff0c;如下图所示,根据系统位数选择x86或者x64进行下载安装,网址&#xff1a;Download .NET 6.0。 IIS启用与配置 启用IIS服务 打开控制面板&#xff…

【Linux】【开发】使用sed命令遇到的乱码问题

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;Linux技术&…

【论文阅读笔记】Supervised Contrastive Learning

【论文阅读笔记】Supervised Contrastive Learning 摘要 自监督批次对比方法扩展到完全监督的环境中&#xff0c;以有效利用标签信息提出两种监督对比损失的可能版本 介绍 交叉熵损失函数的不足之处&#xff0c;对噪声标签的不鲁棒性和可能导致交叉的边际&#xff0c;降低了…

键盘快捷键工具Keyboard Maestro mac中文版介绍

Keyboard Maestro mac是一款键盘快捷键工具&#xff0c;它可以帮助用户通过自定义快捷键来快速完成各种操作&#xff0c;提高工作效率。Keyboard Maestro支持多种快捷键组合&#xff0c;包括单键、双键、三键、四键组合等&#xff0c;用户可以根据自己的习惯进行设置。此外&…

Ribbon

在Spring Cloud中&#xff0c;Ribbon是一个用于客户端负载均衡的组件&#xff0c;它可以与其他服务发现组件&#xff08;例如Eureka&#xff09;集成&#xff0c;以提供更强大的负载均衡功能。Ribbon使得微服务架构中的客户端能够更加智能地调用其他服务的实例&#xff0c;从而…