Java中的双重检查锁(double checked locking)分析

Java中双重检查锁(double checked locking) 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。双重检查锁(Double-Check Locking),顾名思义,通过两次检查,并基于加锁机制,实现某个功能。// 此处如果有多个执行流同时进入,会造成多次初始化// 第1次,一般性检查,但是有并发隐患:可能有多执行流同时进入改处// 此处第2次检查,为了防止后续多执行流并发时,后续获取同步锁的执行流,不会再次初始化Singleton对象。 阅读详情

Java中的双重检查锁(double checked locking)分析

分析通过双重检查锁来获得一个单例时,我主要从3个方面来考虑:

.
① synchronized: 通过在getInstance方法上加上同步锁,进行线程控制


② 双重if判断: 为了避免了在首层判断就加上Synchorzied同步锁,导致锁的粒度过大,导致效率的低下 ,所以采用双重if判断,在第二层判断才引入对性能开销较大的synchorzied锁,双重if判断本质上是对效率的优化


③ volatile : 另外,为了必免jvm在指令优化时,对创建对象(new)过程出现的指令重排序现象,需要组引用对象用volatile修饰

下面我们正式开始分析

相信,我们在解决并发获得单例时,第一想到的就在getInstance方法上加上同步锁。
代码如下:

public class Singleton {
private static Singleton uniqueSingleton;

private Singleton() {
}

public synchronized Singleton getInstance() {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
return uniqueSingleton;
} 
}    

但往往,每个线程在getInstance方法时,都要拿到同步锁,会使得系统开销增大,有点没必要。

优化方案
当已经有一个实例后,通过双重判断,可以使得以后的线程在调用getInstance方法不需要获得同步锁,效率优化。

public class Singleton {
private static Singleton uniqueSingleton;

private Singleton() {
}

public Singleton getInstance() {
if (null == uniqueSingleton) {
synchronized (Singleton.class) {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();   // error
}
}
}
return uniqueSingleton;
}
}   

但还有一个问题,在有些情况下,通过这种方式拿到的Singleton对象,可能是错误的 。

为什么呢?

回顾我们new对象的3个步骤

① 分配内存空间

② 初始化对象

③ 将对象指向刚分配的内存空间

但jvm在指令优化时,会出现步骤②和③对调的情况,比如线程1在经过俩层为null判断后,进入new的动作,在还没有初始化对象时,就返加了地址值,线程2在第一个为null判断时,因为对象已经不为空,那么就直接返回了对象。

这时,就会出现问题。
(虽然我没遇到过此问题,也不清楚这种重排序在实际应用中会导致什么,但大佬都很怕这个问题)

那么,怎么解决呢? 在引用对象前加上volatile关键字,可以解决jvm重排序问题

代码如下

public class Singleton {
private volatile static Singleton uniqueSingleton;

private Singleton() {
}

public Singleton getInstance() {
if (null == uniqueSingleton) {
synchronized (Singleton.class) {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
}   

使用volatile关键词主要可以保证代码的执行顺序不受jvm重排序影响,所以就上面的问题,对象肯定会在初始化后才会返回内存的地址值。

有关volatite的更多介绍,需要借助jvm内存模型,可以参考本人转载文章volatile关键字解析

End!

18-11-11 修正 于松江图书馆


在这里插入图片描述

构建自己的 Qt 插件系统 Qt 本身提供了插件相关的技术,但并没有提供一个通用的插件框架!倘若要开发一个较大的 GUI 应用程序,并希望使其可扩展,那么拥有这样一个插件框架无疑会带来很大的好处。 阅读详情

相关推荐

carsim软件教学

第一步打开小锁(红色标注) 新手往往一看界面是灰的,界面内的各种模块打开不了,以为没激活成功 所有模块必须复制之后,进行编辑,不要直接进行修改(很重要) 2.空气动力学模型(红色标注) 这里面主要设定了簧上质量。整车的整备质量在下图模块中进行设定 空气动力学。主要涉及到空气阻力,在下面模块中进行设定,有个问题需要注意,他的空气阻力与汽车理论的空气阻力公式不一致,这一点需要注意 下面这会模块基本上用不到,涉及到一个声音和汽车的外观 下面这个模块主要涉及到发动机功率,传动比还有 tao,档位的传动比,发

weixin_43796045的博客 2551

Java中的双重检查(Double-Check)详解

Java中的双重检查(Double-Check)详解 文章参考: https://www.cnblogs.com/xiemingjun/p/9628903.html https://zhuanlan.zhihu.com/p/31167297 双重检查锁和单例类 单例类在Java开发者中非常常用,但是它给初级开发者们造成了很多挑战。他们所面对的其中一个关键挑战是,怎样确保单例类的行为是单例?也就是说,无论任何原因,如何防止单例类有多个实例。在整个应用生命周期中,要保证只有一个单例类的实例被创建,双重检查锁(D

杭电鬼先生交流中心 7072

K-means在关键词聚类中的尝试

K-means在文本聚类中的尝试 K-means算法是无监督的聚类算法。它的算法思想是:先随机选取K个对象作为初始的聚类中心。然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。一旦全部对象都被分配了,每个聚类的聚类中心会根据聚类中现有的对象被重新计算。 K-means算法的关键点在于: 初始k个聚类中心的选择 距离的计...

BigPig_LittleTail的博客 5573

深入Java单例模式

在GoF的23种设计模式中,单例模式是比较简单的一种。然而,有时候越是简单的东西越容易出现问题。下面就单例设计模式详细的探讨一下。 所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在。就像是Java Web中的application,也就是提供了一个全局变量,用处相当广泛,比如保存全局数据,实现全局性的操作等。 1. 最简单的实现 首先,...

weixin_33874713的博客 598

Unity安卓打包实战:SDK与JDK配置全攻略

本文详细介绍了Unity安卓打包过程中SDK与JDK的配置方法,包括工具下载、安装步骤、环境变量设置及常见错误排查。通过实战指南帮助开发者快速完成Unity安卓打包环境搭建,提升开发效率。

weixin_30338481的博客 416

【华为OD技术面试真题 - 技术面】- C++面试题(1)

2024华为OD面试手撕代码真题目录以及八股文真题目录

算法大师! 3398

java double check

为了解决这个问题,从Java 1.5开始引入了`volatile`关键字来修饰instance变量,以确保对其的读写操作具有原子性和可见性,禁止了指令重排序,从而解决了double check在旧版JVM中的线程安全问题。最初,在一些旧版JVM实现中,单纯使用double check可能会导致线程安全问题,这是因为编译器和处理器的优化措施可能会导致。在多线程环境下,由于指令重排序的影响,步骤2和步骤3可能被打乱顺序,导致其他线程在初始化完成前就看到了非空但未初始化完成的instance对象。

weixin_34991050的博客 1244

基于反事实的因果推理Causal inference based on counterfactuals--一万六千字文献详细解读(因果关系的推理应用)【全文总结】

基于反事实的因果推理Causal inference based on counterfactuals--一万六千字文献详细解读(因果关系的推理应用)【全文总结】---来自一位即将入学的准研一,也希望这篇文章能够激励自己不断走下去!!

qq_46044325的博客 4442

synchronized同步以及双重检索

一、synchronized同步参考 两个线程同时执行会出错,那么最简单的方法是让CPU执行完一个线程,再执行另一个线程,那么Java中给出了一个非常简单的解决办法,【synchronized】:是一种同步锁。简单解释一下:就是synchronized修饰的代码,同时只能有一个线程执行,即执行完一个线程,再执行另一个,其它需要执行的线程都要排队 。 synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块......

时代新人的博客 1426

XILINX RFSoC全面解析(五)—— Zynq UItrascale+ RF Data Converter IP核详解

这期我们来看看RFSoC独有的IP核——Zynq UItrascale+ RF Data Converter如何使用。 我使用的VIVADO版本是2018.3,这个是最低版本,要开发RFSoC,VIVADO版本必须不低于2018.3。 另外电脑配置也需要很高,64位,8核@3.4GHz CPU,16GB内存,固态硬盘基本就是低配,跑起来很勉强。建议有条件的朋友使用工作站或者服务器。 首先在VIVADO中新建一个工程,因为我使用的是xilinx官方的开发板,所以可以直接设定选board就行。 在I

1万+

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】5.2 数据分组与透视(CUBE/ROLLUP/GROUPING SETS)

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】5.2 数据分组与透视(CUBE/ROLLUP/GROUPING SETS)

kngines 1835

双重检查锁(Double-Checked Locking)的缺陷

双重检查锁(Double-Checked Locking)被广泛用于多线程环境下实现延迟初始化实例,但是它其实是有缺陷的。

极客星云-优快云博客 6767

华为OD机试真题 新系统 2026-04-26 Python&JS 实现【最大化游戏试玩资格分发】

新研发了一台游戏设备可以面向用户接受试玩。现有 n 个试玩申请,每个试玩有开始时间和结束时间。作为协调员,为了能让更多人体验到游戏,你需要对试玩申请进行选择,使得:

MISAYAONE的博客 290

Java中的双重检查锁(double checked locking)

在实现单例模式时,如果未考虑多线程的情况,就容易写出下面的错误代码: public class Singleton { private static Singleton uniqueSingleton; private Singleton() { } public Singleton getInstance() { if (null == uniqueSingleton) { uniqueSingleton = new Single

原&点、、 2080

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

双重校验单例模式(DCL)懒汉模式

先上代码: public class MySingleton { //使用volatile关键字保其可见性 volatile private static MySingleton instance = null; private MySingleton(){} public static MySingleton getInstance() { ...

QAQ123666的博客 884

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

双重检查锁(double-checked locking)

在软件工程中,双重检查锁(double-checked locking[1])是一种设计模式,通过在加锁前检查锁标志(criterion),可以减少加锁的开销。只有当标志显示需要的时候才...

felix021的专栏 4342

Java中的双重检查锁(double checked locking)以及双重检查锁的缺陷

在实现单例模式时,如果未考虑多线程的情况,就容易写出下面的错误代码: public class Singleton { private static Singleton uniqueSingleton; private Singleton() { } public Singleton getInstance() { if (null == u...

非专业技术员的博客 472

Java中的双重检查锁机制模式(double checked locking)

2021年的金三银四一眨眼就到了,对于很多人来说是跳槽的好机会,大厂面试远没有我们想的那么困难,摆好心态,做好准备,你也可以的。另外,面试中遇到不会的问题不妨尝试讲讲自己的思路,因为有些问题不是考察我们的编程能力,而是逻辑思维表达能力;最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。BAT面试经验实战系列:Spring全家桶+Redis等其他相关的电子书:源码+调优其他相关的电子书:源码+调优。

VIP129370的博客 1333

java double-checked locking_Java 中的双重检查锁 (double checked locking)

Java 中的双重检查锁 (double checked locking)最初的代码在最近的项目中, 写出了这样的一段代码privatestaticSomeClassinstance;publicSomeClassgetInstance(){if(null==instance){instance=newSomeClass();}returninstance;}然后在 Code Review 的时候...

weixin_30974667的博客 383

详解Java单例模式中的中双重检查锁(double checked locking)

在实现单例模式时,如果未考虑多线程的情况,就容易写出下面的错误代码: public class Singleton { private static Singleton uniqueSingleton; private Singleton() { } public Singleton getInstance() { if (null == u...

shadow_zed的博客 517

Java中的双重检查锁double checked locking

在实现单例模式时,如果未考虑多线程的情况,就容易写出下面的错误代码: public class Single { private static Single instance; private Single() { } public Singleton getInstance() { if (null == instance) { ...

Angus博客 584
上一篇: 设计模式 之 单例模式 单例的7种写法
下一篇: 几张图轻松理解String.intern()
fedrefdrrhthg
博客等级 码龄9年 63粉丝 43原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值