单例模式:双锁检验学习
时间:2019-03-12
本文章向大家介绍单例模式:双锁检验学习,主要包括单例模式:双锁检验学习使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
先列举最常见的单例模式:
1:懒汉式
Class Singleton{ private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
此方法线程不安全
2:饿汉式
public class SingleTon{ private static SingleTon INSTANCE = new SingleTon(); private SingleTon(){} public static SingleTon getInstance(){ return INSTANCE; }}
加载类时就初始化对象,占用内存
3:双锁检验懒汉式
class Singleton{ private static Singleton instance; private Singleton(){} public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ if(instance==null){ instance = new Singleton(); } } } return instance; } }
此方法看似解决了线程安全问题,实际上还存在隐患,可能出现线程a还在初始化instance但未完全初始化时,线程b就通过instance!=null判断返回了这个instance对象。
这是由于JVM的重排序,导致instance已经指向了一块内存,但这块内存并没有初始化。其根本原因是对象实例化不是原子操作,其顺序可能被重排,可分为三步:
- 1.分配一块内存空间
- 2.在这块内存上初始化一个DoubleCheckLock的实例
- 3.将声明的引用instance指向这块内存
具体原因可参考:https://blog.csdn.net/zy13608089849/article/details/82703192
这里可以给instance加上volatile修饰符禁止jvm重排解决。
其他线程安全的方法还有:
4:静态内部类
public class SingleTon{ private SingleTon(){} private static class SingleTonHoler{ private static SingleTon INSTANCE = new SingleTon(); } public static SingleTon getInstance(){ return SingleTonHoler.INSTANCE; } }
由于内部类只会在getInstance()时才会被加载,且只加载一次,因此也可以看作是线程安全的懒汉式
5:枚举
public enum Singleton{ INSTANCE; }
大概是最简单的单例了哈哈
- 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 数组属性和方法
- 新特性解读 | 数组范围遍历功能
- 技术分享 | MySQL 内存管理初探
- 新特性解读 | 窗口函数的适用场景
- Android自定义View 仿QQ侧滑菜单的实现代码
- Android view随触碰滑动效果
- TextView使用SpannableString设置复合文本 SpannableString实现TextView的链接效果
- FragmentTabHost使用方法详解
- Android编程实现仿优酷圆盘旋转菜单效果的方法详解【附demo源码下载】
- Android绘制圆形百分比加载圈效果
- Android自定义view实现动态柱状图
- Kubernetes集群高可用&备份还原概述 | 知识分享月第三期直播回顾
- SpringCloud2020 学习笔记(一)springboot和springcloud技术选型以及版本选择
- SpringCloud2020 学习笔记(二)父工程搭建
- SpringCloud2020 学习笔记(三) cloud-api-commons通用模块搭建
- SpringCloud2020 学习笔记(四) cloud-provider-payment8001支付模块