单例模式的双重检查
时间:2020-07-12
本文章向大家介绍单例模式的双重检查,主要包括单例模式的双重检查使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
单例模式的双重检查
双重检查
public class Singletone{
private static Instance instance;
public Instance getInstance(){
if(instance == null){
synchronized(Singletone.class){
if(instance == null){
instance = new Instance();
}
}
}
return instance;
}
}
问题:
instance = new Instance();
是由三个步骤组成的:
- 为对象分配内存
- 实例化对象
- 将引用指向对应的内存地址
但是第2,3步可能发生指令重排列,导致先将引用指向一个未实例化对象的内存地址,然后再进行实例化对象。
若此时第二个线程进行第一个非空判断时,则为false,会直接返回还没有实例化对象的内存地址,从而可能产生异常。
解决:
- 禁止指令重排列
- 允许指令重排列,但是其他线程“不可见”
方案一:基于volatile
禁止指令重排列
public class Singletone{
private volatile static Instance instance;
public Instance getInstance(){
if(instance == null){
synchronized(Singletone.class){
if(instance == null){
instance = new Instance();
}
}
}
return instance;
}
}
在成员变量中加入volatile
变量,禁止使用new创建对象时的指令重排列。
方案二:基于类初始化的解决方案
public class Singletone{
private static class InstanceHolder{
public static Instance instance = new Instance();
}
public static Instance getInstance(){
return InstanceHolder.instance;
}
}
JVM在类初始化阶段进行类的初始化。在初始化期间,JVM会获取一个锁,从而同步多个线程对同一个类的初始化。
第一个获得锁的线程会完成实例对象的创建,其他线程会直接获取创建的实例对象。
参考:
原文地址:https://www.cnblogs.com/truestoriesavici01/p/13287258.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 详解Linux动态库生成与使用指南
- Vue 3 入门基础知识
- 在Linux系统中使用Vim读写远程文件的命令详解
- Vue.js实现咸鱼底部Tab凸起|vue自定义导航条组件
- 在Linux中查看所有正在运行的进程的方法
- Apache跨域资源访问报错问题解决方案
- Windows Telemetry服务特权提升
- 滥用DComposition在外部窗口上渲染
- 通过LUMP_PAKFILE的源引擎内存损坏
- MongoDB Change Stream之一——上手及初体验
- MongoDB 慢日志字段解析
- leetcode哈希表之第一个只出现一次的字符
- 转录组RNA-Seq使用docker+bioconda搭建分析环境
- 企业自建GitLab代码仓库安装与基础配置使用
- 全网最全的数据库操作命令,一口气从头看到尾,蛮有收获的!