单例模式与双重锁

2023-05-16

设计模式中,最为基础与常见的就是单例模式。这也是经常在面试过程中被要求手写的设计模式。

下面就先写一个简单的单例:

public class Singleton {

    private static Singleton singleton =new Singleton();

    private void Singleton(){}

    public static Singleton getSingleton(){

        return singleton;

    }

}

上面是饿汉式单例:jvm在启动的时候直接在内存中初始化一个单例对象,我们在调用getSingleton()时直接获取该对象。

public class Singleton {

private static Singleton singleton =null;

    private void Singleton(){}

    public static Singleton getSingleton(){

        if(singleton==null){

            singleton = new Singleton();

        }

        return singleton;

    }

}

上面的是懒汉机制:在jvm启动的时候不会初始化单例对象,只有调用getSingleton()时才去创建对象。多线程的情况下会出现不同步问题,因此需要加锁。

public class Singleton {

private static Singleton singleton =null;

    private void Singleton(){}

    public static synchronized Singleton getSingleton(){

    if(singleton==null){

        singleton  = new Singleton();

        }

    return singleton;

    }

}

懒汉加锁之后,我们调用getSingleton()方法时,会在该方法上面加锁,每次只允许一个线程进入,可以解决同步问题,但是性能会下降。

public class Singleton {

    private static Singleton singleton =null;

    private void Singleton(){}

    public static Singleton getSingleton(){

    if(singleton==null){                                   @1

        synchronized (Singleton.class){          @2

            if(singleton==null){                            @3

                singleton = new Singleton();          @4

                }

        }

    }

        return singleton;

    }

}

在懒汉加锁基础上编程双锁机制:解决了同步时的性能问题。但是在多线程的情况下,还是会出现问题,问题出现在哪里?

 singleton = new Singleton();          @4 

这一步实例化的过程有问题:

这一行代码可以分解为如下的三行伪代码:

  memory = allocate();   //1:分配对象的内存空间

  ctorInstance(memory);  //2:初始化对象

  instance = memory;     //3:设置instance指向刚分配的内存地址

在JIT编译器中,可能会发生重排序。在重排的情况下:如果a,b两个线程同时调用getSingleton()方法,例如a线程先获取到,在a线程 singleton = new Singleton(); 时发生重排,执行1,3,2,执行到3,b线程获取singleton的没有被初始化。

如何解决:

第一:加关键字volatile

public class Singleton {

    private static volatile Singleton singleton =null;

    private void Singleton(){}

    public static Singleton getSingleton(){

        if(singleton==null){

            synchronized (Singleton.class){

                if(singleton==null){

                    singleton =new Singleton();

                    }

            }

        }

    return singleton;

    }

}

Volatile关键字: 可以解决可见性问题,不能确保原子性问题(通过 synchronized 进行解决), 禁止指令的重排序(单例主要用到此JVM规范)。

第二:利用静态内部类

public class Singleton {

    private static Singleton singleton =null;

    private void Singleton(){}

    private static class StaticSingleton{

        private static final Singleton SINGLETON =new Singleton();

    }

    public static Singleton getSingleton(){

        if(singleton==null){

            synchronized (Singleton.class){

                if(singleton==null){

                    singleton = StaticSingleton.SINGLETON;

                }

        }

    }

    return singleton;

    }

}

静态内部类确保在第一次初始化的时候,不用担心并发问题。因为jvm会负责同步整个过程,在初始化进行一半的时候,别的线程无法使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单例模式与双重锁 的相关文章

  • cuda10.0 安装torch1.7.1

    pip install torch1 7 1 43 cu92 torchvision0 8 2 43 cu92 torchaudio 61 61 0 7 2 f https download pytorch org whl torch st
  • 对抗训练

    文章目录 1 定义2 对抗训练 xff1a 从CV到NLP2 1 CV中的数据格式2 2 NLP中数据格式 xff13 对抗样本与数据增强样本 xff14 如何确定微小扰动 xff14 1 Fast Gradient Sign Method
  • 38、带参数的装饰器

    一 带参数的装饰器 我们看 xff0c 装饰器其实就是一个闭包函数 xff0c 再说简单点就是两层的函数 那么是函数 xff0c 就应该具有函数传参功能 login status 61 39 username 39 None 39 stat
  • Git系列:windows10安装Git版本控制工具!

    Git系列 xff1a windows10安装Git版本控制工具 xff01 前言 今天博主将为大家分享Git系列 xff1a windows10安装Git版本控制工具 xff01 不喜勿喷 xff0c 如有异议欢迎讨论 xff01 开始安
  • VNC 连接腾讯云服务器(解决黑屏、灰屏问题)

    整了一天 xff0c 要么黑屏 xff0c 要么灰屏 xff0c 巴拉巴拉 xff0c 最后终于好了 vnc xstartup修改为如下 随后chmod 777 vnc xstartup 就可以了 教程视屏 xff1a https clou
  • 【云计算学习笔记(二十一)】之Neutron子服务详细介绍

    文章目录 本文章由公号 开发小鸽 发布 xff01 欢迎关注 xff01 xff01 xff01 一 xff0e Neutron xff08 一 xff09 Neutron介绍 xff08 二 xff09 Neutron功能1 二层交换Sw
  • 51单片机、DS18B20、智能窗帘控制系统

    写在最前面 xff1a 文章是我的设计报告搬运过来的 xff0c 嫌排版乱的 xff0c 可以直接下载设计报告 xff0c 包含word xff0c keil工程 xff0c proteus工程 xff01 xff01 xff01 xff0
  • 手写RTOS-PendSV中断

    今天这一篇 xff0c 我们说一下操作系统都要用到的PendSV中断 xff0c 整个操作系统中 xff0c 要自己写的的汇编代码不超过20行 xff0c 全部都在PendSV中断里 以下是 Cotex M3权威指南 里对PendSV的描述
  • 如何知道可执行文件是32-bit还是64-bit

    可以使用GetBinaryType API来获得这个信息 xff1a BOOL GetBinaryType LPCTSTR lpApplicationName LPDWORD lpBinaryType Binary Type可以是下面的值
  • 手写RTOS-使用PendSV进行压栈与出栈操作

    学会使用PendSV中断进行压栈和出栈操作 xff0c 是实现任务调度的关键 今天我们就来学习一下如何使用不超过20行的汇编实现压栈和出栈操作 我们现在来实现这么一个例子 xff1a 先把R4 R11通用寄存器的值保存到一个缓冲区里面 xf
  • 树莓派 Ubuntu mate 16.04 下开启vncserver完整教程

    关于开启vncserver的教程 xff0c 在树莓派上不桶系统上 xff0c 有很多教程 xff0c 杂七杂八 这里的环境是 xff1a 树莓派3b 43 Ubuntu 16 04 mate 一 xff1a 在树莓派下完成以下任务 1 安
  • 在linux上安装oracle数据库并通过远程映射建库

    前期准备 安装虚拟机 xff1a 我这里用的VM15 5 xff0c 可用虚拟机有CentOS以及红帽系列版本下载oracle数据库的安装包以及 rpm补丁包 xff0c 并传入linux虚拟机 xff1a 在虚拟机安装VMTools以共享
  • VMware虚拟机Ubuntu无法连接网络的解决办法

    原文来源 1 Ubuntu网络设置 xff1a 依次单击 System Settings gt Network gt Wired gt Options xff0c 如下图所示 xff1a 依次选择 General xff0c 勾选如下图所示
  • Meta-Learning之How to train your MAML

    这篇文章是MAML的升级版本 xff0c 即MAML 43 43 他针对MAML的一些不足之处做了对应的改进 xff0c 如稳定性 收敛速度 表现力等均得到提升 由于自己的算法实现中有用到MAML xff0c 为了让整体算法有一个好的性能
  • 对于中断的笔记

    我们首先要区分内核与外设 内核是为众多应用程序提供对硬件的安全访问的软件芯片 xff0c 如Cortex M4 xff0c 是ARM公司开发的 外设是ST公司在拿到这个内核后 xff0c 制作了相应的硬件 xff0c 如GPIO RTC以及
  • 正则表达式中?=和?:和?!的理解

    要理解 61 和 xff0c 首先需要理解前瞻 xff0c 后顾 xff0c 负前瞻 xff0c 负后顾四个概念 xff1a 前瞻 xff1a exp1 61 exp2 exp1后边是exp2就匹配 后顾 xff1a lt 61 exp2
  • JAVA中的向上转型和向下转型

    一 向上转型和向下转型 向上转型和向下转型是在JAVA继承操作中用到的东西 xff0c 在讲到转型之前我们需要认识到继承过程中的对象类型转换 xff0c 这种转换有两个特点 xff1a 1 这是继承过程中发生的操作 2 新类是现有类的一种类
  • k8s基于kubeadm部署集群 含集群NotReady解决方案

    1 xff09 简介 kubernetes简称k8s 是用于自动部署 xff0c 扩展和管理容器化应用程序的开源系统 中文官网 xff1a https kubernetes io Zh 中文社区 xff1a https www kubern
  • Ubuntu 下 触摸板不能使用 解决方法

    之前好不容易才安装好双系统 xff0c 今天在Ubuntun下安装东西时 xff0c 电脑没电 xff0c 自己关机了 xff0c 重启后 xff0c 触摸板就不能使用了 xff0c 参看了网上 http blog sina com cn
  • 如何安装touch 1.0.1

    如何安装touch 1 0 1 如何安装touch 1 0 1 如何安装touch 1 0 1 今天需要安装 touch 1 0 1 可能是老版本了吧 xff0c 直接使用pip install touch 61 61 1 0 1不能安装成

随机推荐

  • 立创开源|用立创EDA自制ST-Link V2.1调试器

    分享一个2年前在立创开源硬件平台上开源的项目 xff0c 该项目目前是平台上最热门的ST LINK V2 1项目 xff0c 也是点赞数最多的一个ST LINK相关的项目 xff0c 以下是该项目的累积数据 项目作者 xff1a 攻城狮晨哲
  • 一文带你快速理解FreeRTOS代码规范

    关注 星标嵌入式客栈 xff0c 精彩及时送达 导读 遇到些朋友感觉FreeRTOS内核代码看起来很不习惯 xff0c 不习惯其编码风格 xff0c 本文就来梳理一下其代码规范 xff0c 便于提高阅读其代码的效率 代码基于FreeRTOS
  • 校园网经常掉线解决

    我们要访问一个网站 xff0c 通常是在游览器里输入这个网站的网址 xff0c 然后回车 xff0c 这个时候 xff0c DNS 服务器会自动把它解析成 IP 地址 xff0c 实际上我们是通过 IP 来访问网站的 xff0c 网址只不过
  • RHEL7.4 vnc 黑屏问题

    https access redhat com solutions 3167971 环境 Red Hat Enterprise Linux 7 4tigervnc server 1 8 0 1 el7gnome shell 3 22 3 1
  • CentOS 7 禁止 root 直接登陆 及 修改默认端口

    一 禁止 Root 直接登陆 1 新建登陆用户 useradd tom 添加用户 passwd tom 设置密码 2 修改 sshd 配置文件 vi etc ssh sshd config 修改内容 PermitRootLogin no 改
  • 子网划分总结和技巧

    VLSM可变子网掩码对应CIDR值 下面是C类地址的划分技巧 1 确定划分子网数 子网数 61 2 n xff0c n代表子网掩码往右移动的位数 例如 xff1a 要划分2个子网 xff0c 子网掩码需要往右移动1位 xff0c 2 1 6
  • ubuntu虚拟机可以ping通主机但ssh连不上

    其它配置都正确后 xff0c 命令行执行此命令 xff1a service sshd start xff1b
  • android 安卓手机如何投屏到显示器

    这几天有个需求 xff0c 可以手机投屏到显示器上 xff0c 经过一番研究 xff0c 手机连接电脑再投屏是可以的 xff0c but xff0c 要想直接手机插一根线连接显示器 xff0c 只有支持USB3 0及以上的才可以 xff0c
  • sed之两个文件共有特征行的合并输出

    cat a txt 01 12510101 4001 02 12310001 4002 03 12550101 4003 04 12610001 4004 05 12810001 4005 06 12310001 4006 07 12710
  • Mac中有g++/clang,但引用报错:xcrun: error: invalid active developer path (/Library/Developer/Command...

    问题 xff1a 在Mac上安装fasttext的时候 xff0c 发现g 43 43 或者clang都不能直接引用 于是在终端用which检查了一下 xff0c 发现都是存在于 usr bin 目录中的 which g span clas
  • 利用XRDP远程登陆linux系统

    http linux chinaunix net bbs viewthread php tid 61 1149869 一般情况下我们用ssh客户端远程登陆inux系统 xff0c 至于图形界面下的linux 远程登陆工具 xff0c 我们一
  • BOND 动态链路聚合 lacp配置及相关问题

    内容基本都是参考的 xff0c 哪里有雷同或者错的地方 xff0c 请批评指正 针对802 3ad模式的业务分析 xff1a 场景 xff1a 两个千兆网口 xff0c 聚合成bond0 动态链路聚合抓取数据包格式分析 xff1a 后台bo
  • VNC使用介绍

    VNC在内部网络中经常被大家用到 xff0c 该工具同时具备远程操作和传输文件的双重功能 xff0c 而且速度也是很快的 xff0c xff08 低版本不具备文件传输功能 xff09 深受大众喜爱 xff0c 今天就简单写下在使用VNC的过
  • 清除chrome浏览器缓存

    之前有写过设置缓存 本文解决清除html缓存 如何才能清除缓存呢 xff1f 一下是几个清除浏览器缓存的方法 xff1a 方法1 chrome浏览器地址 xff1a chrome settings clearBrowserData xff1
  • Iterator 接口

    具有原生的Iterator 接口的数据结构有 Array Map Set String TypedArray arguments对象 NodeList对象 面我们来实现将class 和 object 也变成迭代的对象 实现的关键就是 Sym
  • 容器和LXC简单命令

    容器和LXC简单命令 文章目录 容器和LXC简单命令一 CGroup xff08 控制组 xff09 的功能1 cgroup xff08 容器控制组 xff09 1 1 功能 xff1a 1 2 具体功能 xff1a 1 3 控制组可以限制
  • Podman设置容器开机自启

    Podman设置容器开机自启 1 podman管理员容器开机自启动 span class token number 1 span span class token operator span span class token operato
  • Linux中tty、pty、pts的概念区别

    http blog sina com cn s blog 638ac15c01012e0v html 基本概念 xff1a 1 gt tty 终端设备的统称 tty一词源于Teletypes xff0c 或teletypewriters x
  • Linux下vnc的安装、使用以及设置开机启动

    安装和使用VNC resbian系统自带realvnc vnc server 启动vnc服务 vncserver 1 xff08 1类似与端口号 xff0c 也可以理解为桌面序号 xff09 关闭vnc服务 vncserver kill 1
  • 单例模式与双重锁

    设计模式中 xff0c 最为基础与常见的就是单例模式 这也是经常在面试过程中被要求手写的设计模式 下面就先写一个简单的单例 xff1a public class Singleton private static Singleton sing