解决多线程环境下单例模式同时访问生成多个实例

如何满足单例:1.构造方法是private、static方法、if语句判断

①、单线程

Single类

//Single类,定义一个GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {System.out.println("创建一次");}public static LazySingleton GetInstance() {//当多线程来临的时候判断是否为null,此时instance就是临界资源,会实例化多个if (instance == null) {instance = new LazySingleton();}return instance;}
}
//客户端代码
public class Main {public static void main(String[] args) {LazySingleton s1= LazySingleton.GetInstance();LazySingleton s2=  LazySingleton.GetInstance();if(s1==s2){System.out.println("两个对象是相同的实例");}}
}

运行结果:

这样的话就满足了单例的效果,保证只实例化一个类,因为LazySingleton封装它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。客户端通过那唯一可以访问的GetInstance方法来访问那一个实例。但如果是多个线程同时调用GetInstance方法,同时运行到了GetInstance方法这儿,它们都会去判断有没有被实例化,判断都为True,那样的话就创建了两个实例,就违背了单例模式,不是一个单例。看下多线程下的单例:

②、多线程

单例类

public class LazySingleton {private static LazySingleton instance;private LazySingleton() {System.out.println("创建一次");}public static LazySingleton GetInstance() {//当多线程来临的时候判断是否为null,此时instance就是临界资源,会实例化多个if (instance == null) {instance = new LazySingleton();}return instance;}
}

main函数

public class Main {public static void main(String[] args) {Runnable r=()->{LazySingleton s1= LazySingleton.GetInstance();LazySingleton s2=  LazySingleton.GetInstance();if(s1==s2){System.out.println("两个对象是相同的实例");}};//两个线程Thread t1= new Thread(r);Thread t2= new Thread(r);t1.start();t2.start();}
}

运行结果:

我们会发现对象被创建了两次,我们通过调试发现s1和s2两个对象的地址实际上是不一样的:

当线程t1刚执行完if (instance == null)判断之后时间片到了,t2线程执行完if (instance == null)判断之后就进入方法体生成了实例,此时t1线程又获得了时间片,t1会接着上次中断的地方继续执行,t1线程便会进入方法体又生成了一个新的实例,此时t1和t2线程各生成了一个实例

如何解决这样一个问题呢?

添加锁,当线程位于临界区的时候就上锁,其他线程来临的时候只能在外排队等待。

③、多线程单例——单锁

单例类

package com.example;public class LazySingleton {private static LazySingleton instance;private LazySingleton() {System.out.println("创建一次");}public static LazySingleton GetInstance() {//当多线程来临的时候判断是否为null,此时instance就是临界资源,会实例化多个//方法:加锁-把判断的这部分逻辑上锁synchronized ("") {if (instance == null) {instance = new LazySingleton();}}return instance;}}

main函数

public class Main {public static void main(String[] args) {Runnable r=()->{LazySingleton s1= LazySingleton.GetInstance();LazySingleton s2=  LazySingleton.GetInstance();if(s1==s2){System.out.println("两个对象是相同的实例");}};//两个线程Thread t1= new Thread(r);Thread t2= new Thread(r);t1.start();t2.start();}
}

运行结果:

发现对象创建了一次。在同一时刻加了锁的那部分程序只有一个线程可以进入,我们可以让最先进入的那个线程先上一把锁,创建实例。后面在进入的线程就不会再去创建对象实例了,因为第一名来的线程已经创建了,你这个判断的结果是False,自然无法创建了。这样的话就保证了多个线程同时访问的话不会有多个实例化。解决了上面单实例带来的问题。但每次进入的线程都需要先加锁在判断,我都还不知道有没有创建过这个实例呢你就让我加锁,第一名已经实例化过了,我进去再加锁,在判断一次,如果有上百个线程同时访问呢,这样的工作重复上百次,不是很影响我这个程序的性能吗?我们就可以用到双重锁定来解决这个问题

④、多线程——双重锁(Double-Check Locking)

package com.example;public class DoubleLockSingleton {private static DoubleLockSingleton instance;private DoubleLockSingleton() {System.out.println("实例化了一次");}public static DoubleLockSingleton GetInstance() {//第一层判断:先判断实例是否存在,不存在再加锁处理if (instance == null) {synchronized ("") {//第二层判断if (instance == null) {instance = new DoubleLockSingleton();}}}return instance;}
}

通过这样两重的判断,进入的线程不用每次都加锁,只是在实例未被创建的时候在加锁处理。同时也保证多线程的安全。

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

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

相关文章

服务器安装系统教程

虽然装好了显卡,但是机器运行一会,CPU就飙升到100%。找售后解决,也没有完全解决。所以这次试试换个别的系统是否能修复。 本来计划是后面组raid、重装系统的,得,又提前了。 这里说一下,这个流程未必是最好…

ChatGPT在工作中的七种用途

1. 用 ChatGPT 替代谷歌搜索引擎 工作时,你一天会访问几次搜索引擎?有了 ChatGPT,使用搜索引擎的频率可能大大下降。 据报道,谷歌这样的搜索引擎巨头,实际上很担心用户最终会把自己的搜索工具换成 ChatGPT。该公司针对…

【FAQ】RTSP/Onvif协议安防监控EasyNVR调用接口录像会被自动删除是什么原因?

EasyNVR安防视频云服务是基于RTSP/Onvif协议接入的视频平台,可支持将接入的视频流进行全平台、全终端的分发,分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等。平台丰富灵活的视频能力,可应用在智慧校园、智慧工厂、智慧水利等…

Docker Compose编排部署LNMP服务

目录 安装docker-ce 阿里云镜像加速器 文件 启动 安装docker-ce [rootlocalhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo --2023-08-03 18:34:32-- http://mirrors.aliyun.com/repo/Centos-7.repo 正在解析主机 m…

Hive数据仓库

数据仓库概念与起源发展由来 数仓概念 数据仓库(英语:Data Warehouse,简称数仓、DW),是一个用于存储、分析、报告的数据系统。数据仓库的目的是构建面相分析的集成化数据环境,分析结果为企业提供决策支持…

iTOP-RK3568开发板Windows 安装 RKTool 驱动

在烧写镜像之前首先需要安装 RKTool 驱动。 RKTool 驱动在网盘资料“iTOP-3568 开发板\01_【iTOP-RK3568 开发板】基础资料 \02_iTOP-RK3568 开发板烧写工具及驱动”路径下。 驱动如下图所示: 解压缩后,进入文件夹,如下图所示:…

LeetCode 热题 100 JavaScript--102. 二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] 示例 2: 输入:root [1…

Postgresql源码(109)并行框架实例与分析

1 PostgreSQL并行参数 系统参数 系统总worker限制:max_worker_processes 默认8 系统总并发限制:max_parallel_workers 默认8 单Query限制:max_parallel_workers_per_gather 默认2 表参数限制:parallel_workers alter table tbl …

easyui实用点

easyui实用点 1.下拉框(input框只能选不能手动输入编辑) data-options"editable:false"//不可编辑2.日期框,下拉框,文本框等class class"easyui-datebox"//不带时分秒 class"easyui-datetimebox"…

C++类与对象(上)

目录 类的定义类的访问限定符类的实例化类对象大小和储存方式this指针 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象…

WSL2安装CentOS7和CentOS8

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、下载ZIP包?二、安装1.打开Windows子系统支持2.安装到指定位置3.管理虚拟机4.配置虚拟机1.配置国内源2.安装软件3.安装第三方源 5.配置用户1.创建…

【ASP.NET MVC】数据到客户端(7)

前文ViewBag数据在服务端动态生成页面,也可以传到客户端浏览器供JS使用。 一、数据从控制器到客户端 前文介绍,动态生成页面时,控制器的数据 并没有传递到 客户端,而是给自己来用,生成View 再利用http传递到客户端浏…

神经概率语言模型

本文主要参考《A Neural Probabilistic Language Model》这是一篇很重要的语言模型论文,发表于2003年。主要贡献如下: 提出了一种基于神经网络的语言模型,是较早将神经网络应用于语言模型领域的工作之一,具有里程碑意义。采用神经网络模型预测下一个单词…

Linux环境下VS code的python与C++调试环境的安装

Linux环境下VS code的python与C调试环境的安装 文章目录 Linux环境下VS code的python与C调试环境的安装前言一、云服务器的环境二、VS code相关信息三、python 开发环境配置四、C开发环境配置1.测试main.cpp2.进行debug3.进行debug程序4.运行main.cpp程序步骤 前言 最近写的 C&…

Meta AI研究团队新AI模型: Llama 2 大语言模型

Llama是Facebook Research团队开发的基础语言模型集,旨在提供广泛的语言理解能力。它基于转换器架构,参数范围从7B到65B。通过使用Llama模型,研究人员和开发人员可以构建更先进的自然语言处理系统。您可以在GitHub上找到相关的代码和资源&…

【BASH】回顾与知识点梳理(二)

【BASH】回顾与知识点梳理 二 二. Shell 的变量功能2.1 什么是变量?2.2 变量的取用与设定: echo, 变量设定规则: set/unset2.3 环境变量的功能用 set 观察所有变量 (含环境变量与自定义变量)export: 自定义变量转成环境变量那如何将环境变量转成自定义变…

【Spring Cloud 五】OpenFeign负载均衡

这里写目录标题 系列文章目录背景一、OpenFeign是什么Feign是什么Feign的局限性 OpenFeign是什么 二、为什么要有OpenFeign三、如何使用OpenFeign服务提供者order-servicepom文件yml配置文件启动类实体ParamController 服务消费者user-servicepom文件yml配置文件启动类接口类Us…

怎么维护自己的电脑?

方向一:我的电脑介绍 我使用的是一台来自知名品牌的笔记本电脑。它具有高性能的核心配置,如快速处理器、大容量内存和高性能显卡,以及宽敞的存储空间。我选择这台电脑主要是因为它的出色性能和可靠性,能够满足我在学习和工作中的…

Bean的实例化方法

目录 1.工厂模式通常有三种形态: 2.简单工厂 2.1 静态工厂 2.1通过factory-bean实例化 2.3通过FactoryBean接口实例化 3.测试 关于容器的使用 3.1获得spring文件方式 3.2getBean方式 4.关闭容器 1.工厂模式通常有三种: 第一种:简单工…

(杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(5)

1001 Typhoon 计算几何 对于每一个避难点,计算其到所有线段的距离,取min即可 AC代码&#xff1a; #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<deque> #include<cmath> #include<cstdio&…