DCL(Double Check Lock双重检锁机制)解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题

简介: DCL(Double Check Lock双重检锁机制)解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题

DCL(Double Check Lock双重检锁机制)解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题


一、前言

我们在使用单例模式时,一般有两种选择,一个是懒汉式,一个是饿汉式。但是这两种都是有各自的缺点,无法满足我们的需求,所以DCL(Double Check Lock双端检锁机制)出现了,一种既支持延迟加载、又支持高并发的单例实现方式。

如果不清楚懒汉式为什么不支持高并发可以看一下这篇文章—>

单例模式的懒汉模式为什么在高并发中会出现问题

其他解决方案—>


静态内部类解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题


利用枚举特性解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题


二、具体实现

- DCL单例模式

import lombok.Data;
import java.util.concurrent.atomic.AtomicInteger;
@Data
public class Phone {
    //手机余额
    private AtomicInteger count = new AtomicInteger(3);
    private Phone(){}
    private static Phone phone;
    public static Phone getInstance(){
        if (phone == null){
            synchronized(Phone.class) { // 此处为类级别的锁
               if (phone == null) {
                   phone = new Phone();
               }
            }
        }
        return phone;
    }
    public int getReduce(){
        return count.decrementAndGet();
    }
}

- 并发测试类

public class BingFa {
    public static void main(String[] args) {
        // 创建3个线程,线程里面进行加操作
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                Phone phone = Phone.getInstance();
                int reduce = phone.getReduce();
                System.out.println(Thread.currentThread().getName()+
                          "线程抢到了手机,剩余手机数量"+"-----"+reduce);
            }, String.valueOf(i)).start();
        }
    }
}

- 测试结果


三、总结

这样就解决了并发问题,懒汉式本来就是懒加载,我们看到三台手机被三个线程抢到了,完美解决问题!!!


附:网上有人说,这种实现方式有些问题。因为指令重排序,可能会导致 Phone对象被 new 出来,并且赋值给 phone之后,还没来得及初始化(执行构造函数中的代码逻辑),就被另一个线程使用了。要解决这个问题,我们需要给 phone成员变量加上 volatile 关键字,禁止指令重排序才行。实际上,只有很低版本的 Java 才会有这个问题。我们现在用的高版本的 Java 已经在 JDK 内部实现中解决了这个问题(解决的方法很简单,只要把对象 new 操作和初始化操作设计为原子操作,就自然能禁止重排序)。

本段话来自极客时间王老师

相关文章
|
设计模式 安全 NoSQL
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
179 0
|
设计模式 安全 Java
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
171 0
|
设计模式 安全 Java
【Java|多线程与高并发】设计模式-单例模式(饿汉式,懒汉式和静态内部类)
设计模式是一种在软件开发中常用的解决复杂问题的方法论。它提供了一套经过验证的解决方案,用于解决特定类型问题的设计和实现。设计模式可以帮助开发人员提高代码的可重用性、可维护性和可扩展性。
|
SQL Java
解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题最简单方法——基于枚举类型的单例实现
解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题最简单方法——基于枚举类型的单例实现
228 0
解决单例模式中懒汉式不支持高并发,饿汉式不支持懒加载问题最简单方法——基于枚举类型的单例实现
|
设计模式
单例模式的懒汉模式为什么在高并发中会出现问题?一个代码例子告诉你
单例模式的懒汉模式为什么在高并发中会出现问题?一个代码例子告诉你
150 0
单例模式的懒汉模式为什么在高并发中会出现问题?一个代码例子告诉你
|
Dubbo 应用服务中间件
Dubbo源码Debug-Double Check考点
![image.png](https://ata2-img.cn-hangzhou.oss-pub.aliyun-inc.com/76230c3baf735828dedd39eca3c4d015.png) 说说看,你觉得这个在多线程并发的情况下会有问题吗? ![image.png](https://ata2-img.cn-hangzhou.oss-pub.aliyun-inc.com/
574 0
|
测试技术
《设计模式》学习笔记5——单例模式【高并发拓展】
定义 单例模式又称为单件模式,这个模式大概是设计模式中最好理解的了,我起初就打算从这里开始学,甚至还记过另一篇单例模式学习的笔记。 但是之后跟着《设计模式》这本书系统的学,就索性从第一页开始,而单例模式算是复习,也算是再深入的理解一次。
2131 0
|
存储 Java
百度搜索:蓝易云【Java语言之float、double内存存储方式】
由于使用IEEE 754标准进行存储,float和double类型可以表示非常大或非常小的浮点数,并且具有一定的精度。然而,由于浮点数的特性,它们在进行精确计算时可能会存在舍入误差。在编写Java程序时,需要注意使
205 0
|
11月前
|
存储 关系型数据库 MySQL
double ,FLOAT还是double(m,n)--深入解析MySQL数据库中双精度浮点数的使用
本文探讨了在MySQL中使用`float`和`double`时指定精度和刻度的影响。对于`float`,指定精度会影响存储大小:0-23位使用4字节单精度存储,24-53位使用8字节双精度存储。而对于`double`,指定精度和刻度对存储空间没有影响,但可以限制数值的输入范围,提高数据的规范性和业务意义。从性能角度看,`float`和`double`的区别不大,但在存储空间和数据输入方面,指定精度和刻度有助于优化和约束。
1651 5
|
存储 C语言
C 语言实例 - 计算 int, float, double 和 char 字节大小
C 语言实例 - 计算 int, float, double 和 char 字节大小。
178 1

热门文章

最新文章