多线程案例--单例模式

目录

一.什么是单例模式

二.饿汉模式

三.懒汉模式

3.1.单线程版

3.2.多线程版


一.什么是单例模式

单例模式是校招中最常考的设计模式之一

什么是设计模式:软件开发过程中会遇到很多常见的问题场景。针对这些问题场景,大佬们总结了一套固定的套路,按照这个套路实现代码,不会吃亏。

单例模式能保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例。

单例模式具体的实现方式有很多.最常见的是"饿汉"和"懒汉"两种。

二.饿汉模式

类加载的同时就创建实例,并且将构造方法私有化(尽量早创建)

java 复制代码
class Singleton{
    private static Singleton instance=new Singleton();//类加载初始化,JVM保证线程安全
    public static Singleton getInstance(){
        return instance;
    }
    private Singleton(){

    }
}

静态成员初始化是在类加载的初始化阶段 触发的;类加载不是程序一启动就触发 ,而是第一次使用该类时 才触发;return 只是读操作,不涉及修改;静态变量只会创建并初始化一次 ;静态变量 / 静态代码块的初始化由 JVM 保证线程安全 ,JVM 在类初始化时会自动加锁 ,确保多线程下只会执行一次,不会产生线程安全问题

三.懒汉模式

3.1.单线程版

类加载的时候不创建实例.第一次使用的时候才创建实例(尽量晚创建)

java 复制代码
class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
           instance = new Singleton();
        }
       return instance;
     }
 }

如果是单线程的话,完全是可以实现单例模式的,但是多线程就不行了,会产生线程安全问题

3.2.多线程版

这里需要进行加锁操作,以防线程调度

导致这种现象产生(不再是只实例化一个对象)

java 复制代码
class SingletonLazy{
    private static  SingletonLazy instance=null;
    private static Object loker=new Object();
    public static SingletonLazy getInstance(){
            synchronized (loker) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
                System.out.println(Thread.currentThread().getName()+"解锁");
            }
        return instance;
    }
    private SingletonLazy(){

    }
}

虽然这个代码已经线程安全了,但是还是有问题,我们可以看到,这个加锁操作并不是按需求加锁,如果实例创建了,就不涉及到线程安全的问题了,按理说就不需要加锁了,过度的加锁会导致后续线程阻塞等待,降低效率,所以我们可以在加锁之前做一个判断

java 复制代码
class SingletonLazy{
    private static SingletonLazy instance=null;
    private static Object loker=new Object();
    public static SingletonLazy getInstance(){
        if(instance==null) {
            System.out.println(Thread.currentThread().getName()+"判断instance是null的,加锁操作,避免过度枷锁");
            synchronized (loker) {
                System.out.println(Thread.currentThread().getName()+"被加锁");
                if (instance == null) {
                    System.out.println(Thread.currentThread().getName()+"判断instance是null的,创建新对象");
                    instance = new SingletonLazy();
                }
                System.out.println(Thread.currentThread().getName()+"解锁");
            }
        }
        return instance;
    }
    private SingletonLazy(){

    }
}

第一个if判断是为了避免过度加锁,第二个if是为了判断是否已经实例化对象。

但是这就完了吗?nonono,当然没有,我们上一张讲到的JVM 为了提高效率,会自作主张将长期未变,并且用的次数很多的数据存储在寄存器中直接拿取,其实JVM 为了优化效率还会进行指令重排的操作。

创建实例的步骤:1.创建内存。2.构造对象,初始化。3.把内存地址赋值给引用。如果不加上限制的话可能会导致指令重排,可能顺序为1,3,2.就会导致得到的是一个半初始化的对象,得到的是一个空格子,没有具体内容。

java 复制代码
class SingletonLazy{
    private static volatile SingletonLazy instance=null;
    private static Object loker=new Object();
    public static SingletonLazy getInstance(){
        if(instance==null) {
            System.out.println(Thread.currentThread().getName()+"判断instance是null的,加锁操作,避免过度枷锁");
            synchronized (loker) {
                System.out.println(Thread.currentThread().getName()+"被加锁");
                if (instance == null) {
                    System.out.println(Thread.currentThread().getName()+"判断instance是null的,创建新对象");
                    instance = new SingletonLazy();
                }
                System.out.println(Thread.currentThread().getName()+"解锁");
            }
        }
        return instance;
    }
    private SingletonLazy(){

    }
}

public class Demo1{
    public static void main(String[] args) {
        Thread t1=new Thread(()->{
            SingletonLazy.getInstance();
        });
        Thread t2=new Thread(()->{
            SingletonLazy.getInstance();
        });
        t1.start();
        t2.start();
    }
}
相关推荐
今天会营业11 天前
单例模式:饿汉和懒汉
单例模式
小小晓.11 天前
C++单例模式万字详解:6种实现演进+线程安全彻底解决+CRTP终极模板
c++·单例模式
软件黑马王子12 天前
3.单例模式问题1:构造函数
开发语言·单例模式·c#
软件黑马王子12 天前
4.单例模式问题2:重复挂载
开发语言·单例模式·c#
软件黑马王子13 天前
5.单例模式问题3:多线程问题
单例模式·前端框架·c#
旧梦952716 天前
Java 单例模式:从基础到实战的完整指南
java·开发语言·单例模式
码匠许师傅17 天前
【设计模式精讲】4.单例模式(Singleton)
c++·单例模式·设计模式
米啦啦.18 天前
设计模式/
观察者模式·单例模式·设计模式·工厂模式
布莱克60518 天前
单例模式详解:什么是单例模式,它能解决哪些问题?
开发语言·qt·单例模式
拓人间精准客18 天前
ToB 销售获客避坑指南:如何用全维度大数据实现降本增效
大数据·数据结构·单例模式