一、设计模式

在讲解单例模式之前,我们先来看一下什么是设计模式。

在实际的软件开发中,我们肯定会碰到很多典型的实际问题来进行解决,而针对这些实际的问题有的人就总结出了特定的一套解决方案来进行问题的解决。

设计模式中就提供给了我们很多典型场景的解决问题的处理方式。

二、单例模式

在单例模式中又分为两种模式,一种是饿汉模式,一种是懒汉模式。

  • 饿汉模式:程序启动,类加载之后就会立即创建出实例。
  • 懒汉模式:在第一次使用实例的时候在创建实例,否则能不创建实例就不创建实例。

饿汉模式

我们来写一段代码进行单例模式(饿汉模式)的举例,请看:

class Singleton {
    private static Singleton instance = new Singleton();
    public static Singleton getInstance() {
        return instance;
    }
}

public class Demo17 {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println(s1 == s2);
    }
}

懒汉模式

我们依然是写一段代码来进行举例,请看:

class Singletonlazy {
    private static Singletonlazy instance = null;
    public static Singletonlazy getInstance() {
        if(instance == null) {
            instance = new Singletonlazy();
        }
        return instance;
    }
    private Singletonlazy() {}
}

public class Demo18 {
    public static void main(String[] args) {
        Singletonlazy s1 = Singletonlazy.getInstance();
        Singletonlazy s2 = Singletonlazy.getInstance();
        System.out.println(s1 == s2);
    }
}

三、线程安全问题

我们现在来看看饿汉模式和懒汉模式中的线程安全问题。

饿汉模式的线程安全问题

【Java系列】多线程案例学习——单例模式-LMLPHP

饿汉模式中的线程安全问题解释:当我们多次调用getInstance方法的时候,并不会修改实例instance的内容,同时我们直到多线程读取同一个变量的时候,此时是不会出现线程安全的问题的,因为多线程读取同一个变量的时候是不会对变量进行修改的;因为在这里并不会修改instance实例中的内容。综上,饿汉模式并不会引起线程安全的问题。

懒汉模式的线程安全问题

【Java系列】多线程案例学习——单例模式-LMLPHP
线程A获取到锁,并创建了一个新的Singletonlazy实例并将其赋值给instance。
然后,线程B获取到锁,由于此时instance不为null,线程B也会创建一个新的Singletonlazy实例并将其赋值给instance。这样,就导致了多个实例的创建,违反了单例模式的定义。

指令重排序

【Java系列】多线程案例学习——单例模式-LMLPHP
如上图,创建出实例对象这个操作站在指令的角度就可以分为三个步骤进行执行:

  • 第一步:给对象创建出内存空间,得到内存地址
  • 第二步:在空间上调用内存方法,对对象进行初始化
  • 第三步:把内存地址赋值给instance引用

本文到这里就结束了,希望友友们可以支持一下一键三连哈。嗯,就到这里吧,再见啦!!!

【Java系列】多线程案例学习——单例模式-LMLPHP

12-24 20:31