当前位置: 首页 > news >正文

Java面试题(二十三)DCL单例

懒汉式单例

    private static SingletonInstance INSTANCE;private SingletonInstance(){}public static SingletonInstance getInstance() {if (INSTANCE == null) {INSTANCE = new SingletonInstance();}return INSTANCE;}

构造方法私有化,然后判断是否为空,如果是空,就new一个实例对象,单线程下看似没什么问题,但是如果是多线程,就会有问题了

如果有多个线程同时进入if (INSTANCE == null) 这个判断,那就会生成多个对象了,就不是单例对象了

好我们来加锁看下效果

    private static SingletonInstance INSTANCE;private SingletonInstance(){}public synchronized static SingletonInstance getInstance() {if (INSTANCE == null) {INSTANCE = new SingletonInstance();}return INSTANCE;}

这样加上锁之后是不是就解决了多个线程的问题呢
但是有个问题,就是锁粒度太大了,加在方法上,那有100个线程一上来就会先竞争锁,性能非常低,我们把锁粒度缩小点

    private static SingletonInstance INSTANCE;private SingletonInstance(){}public static SingletonInstance getInstance() {synchronized (SingletonInstance.class){if (INSTANCE == null) {INSTANCE = new SingletonInstance();}}return INSTANCE;}

把synchronized 放在 方法里面,锁粒度降低了,但是还是会存在100个线程进来就竞争锁,性能还是很低,接着优化

    private static SingletonInstance INSTANCE;private SingletonInstance(){}public static SingletonInstance getInstance() {if (INSTANCE == null) {synchronized (SingletonInstance.class){if (INSTANCE == null) {INSTANCE = new SingletonInstance();}}}return INSTANCE;}

我们在synchronized外层套一个是否为空的判断,如果100个线程进入方法,此时第一个线程拿到锁,然后new了算力对象,然后释放锁资源,此时第2个线程会先判断是否为空,如果不为空直接返回对象,如果是空然后再去拿锁,拿到锁之后又会做个判断是否为空,因为第一个线程已经创建实例,所以这里判断不为空直接返回对象,后面第3,第4 … 等线程 都是一样的逻辑

这样通过Double Check Lock 双重检查锁的机制解决了多线程的问题,那么这样就完美的解决多线程问题了吗?

Java创建对象过程

我们来看下Java创建对象的过程,主要分为3步

  1. new 一个对象 分配空间,赋默认值
  2. 调用构造方法,初始化赋值
  3. 将引用变量指向这个内存地址

jvm并不是完全按照123这个步骤去创建对象的,有可能是先执行第一步,再执行第三步,然后执行第二步,这就是Java中的指令重排序现象,结合刚刚上面说的,如果现在有100个线程,第一个线程new了一个实例对象,也就是完成第一步,然后执行第三步,此时这个对象就是一个半成品,因为他还没有执行第2步,这样的话如果第二个线程进来,判断是否为空,不为空,直接返回实例对象,此时的这个对象就是个半成品,那么如果解决这个问题呢?

volatile关键字

volatile关键字有个特性就是禁止指令重排序,就是必须按照123这个步骤往下执行,来看下代码

    //volatile 关键字private static volatile SingletonInstance INSTANCE;private SingletonInstance(){}public static SingletonInstance getInstance() {if (INSTANCE == null) {synchronized (SingletonInstance.class){if (INSTANCE == null) {INSTANCE = new SingletonInstance();}}}return INSTANCE;}
http://www.lryc.cn/news/31618.html

相关文章:

  • UML-类图
  • PostgreSQL 数据库和 pgAdmin 4
  • quarkus 搭建与基础开发环境配置总结
  • 扩散模型DDPM开源代码的剖析【对应公式与作者给的开源项目,diffusion model】
  • C语言 学生记录管理系统
  • 【独家】华为OD机试 C 语言解题 - 交换字符
  • 网络安全平台测试赛 easyphp(phar脏数据处理)
  • 【python】XML格式文件读写详解
  • 理解js的精度问题
  • 蓝桥杯 时间显示
  • qt中设置菜单高度
  • 测开:前端基础-css页面布局-定位
  • Servlet中八个监听器介绍
  • LicenseBox Crack,对服务器的要求最低
  • css中重难点整理(vertical-align)
  • javaScript基础面试题 ---宏任务微任务
  • 基于JSP的网上书城
  • C#教程 05 常量
  • 【华为OD机试真题java、python】基站维修工程师【2022 Q4 100分】(100%通过)
  • 你是真的“C”——为冒泡排序升级赋能!
  • 【JavaEE】基于mysql与servlet自制简易的表白墙程序
  • 抓包技术(浏览器APP小程序PC应用)
  • linux笔记(10):ubuntu环境下,基于SDL2运行lvgl+ffmpeg播放mp4
  • JavaScript专题之类型判断(下)
  • 【VC 7/8】vCenter Server 基于文件的备份和还原Ⅲ—— 使用 SMB 协议备份 VC(VAMI 中文)
  • linux - 内核编译
  • Spring——配置文件实现IOC和DI入门案例
  • 机器学习100天(四十一):041 对偶支持向量机-公式推导
  • C语言下的signal()函数
  • google独立站和与企业官网的区别是什么?