Java双重校验单例模式详解
单例模式双重检测java实现:
public class Singleton {
private volatile static Singleton instance = null; //#1
public static Singleton getInstance() {
if (instance == null) { //#2
synchronized (SingletonClass.class) { //#3
if(instance == null) { //#4
instance = new Singleton();
}
}
}
return instance;
}
1.1:为什么要使用volatile?
通常来说在堆中创建变量,会有两个步骤:
在堆中分配内存空间、执行初始化(就是new做得事情)
在栈中的本地变量表分配一个指向该内存区域的reference(等于号做得事情)
但JVM会进行编译优化,并不一定按照这样的顺序执行。在多线程环境下,若线程A创建instance,首先分配了reference的指针,此时线程B并发地去执行getInstance方法,那么会发现instance所指向的内存区域并不是null,那么线程B的getInstance方法则会返回这个instance,但实际上线程A仅仅是分配了这个指针,并没有在内存区域中完成初始化方法。
volatile禁止了JVM对指令顺序的优化,使得创建变量严格按照先分配内存再分配指针的顺序执行。
同时,如果没有volatile,某线程修改变量,并不会立即存入共享内存(主存),而是存入线程私有的一块高速缓存区域(在CPU中的cache),而volatile要求线程对变量修改完之后立即存入共享内存,保证了变量修改的可见性。
1.2:为什么要static?
保证单例对象是属于类的,而不是属于对象实例的,保证一个类只有一个变量。
3 为什么不给getInstance方法修饰synchronized,而是在这里给类上锁?
因为没有必要,如果在最外层判断出已有单例对象,则无需调用任何同步方法。而若给getInstance方法修饰synchronized,那么无论如何都有synchronized带来的额外开销(即便synchronize进行了大量优化)。
4 为什么需要第二层检验?
在多线程环境下,若没有语句#4,想象这样的场景:
线程A执行完#2
在#2、#3之间发生了线程切换,切换到线程B
线程B执行#3,获取到了锁,并进行instance初始化
切换回线程A,线程A执行#3,获取到了锁,并进行instance初始化
会发现instance被初始化了两次,因此必须进行第二层检验。
Java双重校验单例模式详解的更多相关文章
- Java设计模式之单例模式详解
在Java开发过程中,很多场景下都会碰到或要用到单例模式,在设计模式里也是经常作为指导学习的热门模式之一,相信每位开发同事都用到过.我们总是沿着前辈的足迹去做设定好的思路,往往没去探究为何这么做,所以 ...
- 9种Java单例模式详解(推荐)
单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象. 懒汉式(线程不安全) 其主要表现在单例类在外 ...
- java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock
原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...
- Java 8 Stream API详解--转
原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...
- java反射机制深入详解
java反射机制深入详解 转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...
- 国际化,java.util.ResourceBundle使用详解
java.util.ResourceBundle使用详解 一.认识国际化资源文件 这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以: 轻松地本地化或翻译成不同的 ...
- java之StringBuffer类详解
StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ...
- java.util.ResourceBundle使用详解
java.util.ResourceBundle使用详解 一.认识国际化资源文件 这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以: 轻松地本地化或翻译成不同的 ...
- java之AbstractStringBuilder类详解
目录 AbstractStringBuilder类 字段 构造器 方法 public abstract String toString() 扩充容量 void expandCapacity(in ...
随机推荐
- XCTF练习题---CRYPTO---混合编码解析
XCTF练习题---CRYPTO---混合编码解析 flag:cyberpeace{welcometoattackanddefenceworld} 解题步骤: 1.观察题目,下载附件进行查看 2.看到 ...
- XCTF练习题---CRYPTO---Morse解析
XCTF练习题---CRYPTO---Morse解析 flag:morsecodeissointeresting 解题步骤: 1.观察题目,下载附件进行查看 2.得到文件内容,由0.1组成,初步判断为 ...
- 学习HTTP——HTTPS
前言 因为工作需要,需要用到大量的关于 HTTP 协议的知识,目前掌握的关于 HTTP 请求以及协议的知识都是零散的,打算针对知识盲区系统的学习一些,理清概念. 为什么会出现 HTTPS 因为 HTT ...
- linux项目部署(非前后端分离crm)
参考博客 参考博客2---部署过程 导论:看参考博客1 WSGI是Web服务器网关接口.它是一个规范,描述了Web服务器如何与Web应用程序通信,以及Web应用程序如何链接在一起以处理一个请求,(接收 ...
- Java遇上SPL:架构优势和开发效率,一个不放过
摘要:如果我们在Java中也提供有一套完整的结构化数据处理和计算类库,那这个问题就能得到解决:即享受到架构的优势,又不致于降低开发效率. 本文分享自华为云社区<Java结构化处理SPL>, ...
- .net 项目使用 JSON Schema
.net 项目使用 JSON Schema 最近公司要做配置项的改造,要把appsettings.json的内容放到数据库,经过分析还是用json的方式存储最为方便,项目改动性最小,这就牵扯到一个问题 ...
- 基于DEM的坡度坡向分析
坡度坡向分析方法 坡度(slope)是地面特定区域高度变化比率的量度.坡度的表示方法有百分比法.度数法.密位法和分数法四种,其中以百分比法和度数法较为常用.本文计算的为坡度百分比数据.如当角度为45度 ...
- 将汇总结果导出到MySQL
①mysql建表test1 ②cd /opt/module/sqoop进入scoop路径 ③ bin/sqoop export \ > --connect jdbc:mysql://master ...
- 【系统问题】windows10打印就蓝屏-报错误代码“win32kfull.sys”
现象描述: 打印机一打印电脑就蓝屏,蓝屏错误代码为:win32kfull.sys 原因分析: 2021年3月9日-推送了KB5000802补丁更新(操作系统内部版本19041.867和19042.86 ...
- 《Unix 网络编程》05:TCP C/S 程序示例
TCP客户/服务器程序示例 系列文章导航:<Unix 网络编程>笔记 目标 ECHO-Application 结构如下: graph LR; A[标准输入/输出] --fgets--> ...