Java双重校验锁单例原理

Java双重校验锁单例原理攻略

在Java中,单例模式是一种常见的设计模式,用于确保一个类只有一个实例,并提供全局访问点。其中,双重校验锁是一种常用的实现方式,它结合了懒加载和线程安全的特性。本攻略将详细讲解Java双重校验锁单例的原理,并提供两个示例说明。

原理解析

双重校验锁单例模式的核心思想是在保证线程安全的前提下,尽可能地减少锁的使用,以提高性能。它的实现过程如下:

  1. 私有化构造函数:将类的构造函数私有化,使得其他类无法直接实例化该类。
  2. 声明一个私有的静态变量:用于保存单例实例。
  3. 提供一个公共的静态方法:用于获取单例实例。
  4. 双重校验锁:在公共方法中使用双重校验锁,确保只有第一次调用时才会创建实例。

下面是一个示例代码:

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {
        // 私有化构造函数
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

在上述代码中,volatile关键字用于确保多线程环境下的可见性,避免指令重排序导致的问题。双重校验锁的关键在于两次判断instance是否为null,第一次判断是为了避免不必要的同步开销,第二次判断是为了在实例创建之前,避免其他线程已经创建了实例。

示例说明

示例一:多线程环境下的单例模式

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {
        // 私有化构造函数
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

public class Main {
    public static void main(String[] args) {
        Runnable task = () -> {
            Singleton singleton = Singleton.getInstance();
            System.out.println(\"Thread: \" + Thread.currentThread().getName() + \", Singleton: \" + singleton);
        };

        // 创建多个线程并同时获取单例实例
        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);
        thread1.start();
        thread2.start();
    }
}

在上述示例中,我们创建了两个线程并同时获取单例实例。由于双重校验锁的存在,只会有一个线程创建实例,其他线程会等待。输出结果类似于:

Thread: Thread-0, Singleton: Singleton@1a2b3c4d
Thread: Thread-1, Singleton: Singleton@1a2b3c4d

可以看到,两个线程获取到的实例是相同的,符合单例模式的要求。

示例二:延迟加载的单例模式

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {
        // 私有化构造函数
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

public class Main {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        System.out.println(\"Singleton1: \" + singleton1);
        System.out.println(\"Singleton2: \" + singleton2);
    }
}

在上述示例中,我们直接调用getInstance方法获取单例实例。由于双重校验锁的存在,实例只会在第一次调用时创建,之后的调用会直接返回已创建的实例。输出结果类似于:

Singleton1: Singleton@1a2b3c4d
Singleton2: Singleton@1a2b3c4d

可以看到,两次获取到的实例是相同的,符合单例模式的要求。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java双重校验锁单例原理 - Python技术站

(0)
上一篇 2023年8月2日
下一篇 2023年8月2日

相关文章

  • Win10系统怎么添加环境变量?

    添加环境变量是为了让系统能够找到需要的特定命令或程序。下面是在Win10系统中添加环境变量的步骤: 1. 打开“系统属性”窗口 通过以下两种方式都能打开该窗口: 在文件资源管理器中,右击“此电脑”图标,选择“属性”; 按下Windows按键+R组合键,输入“sysdm.cpl”后回车。 2. 选择“高级系统设置” 在“系统属性”窗口中的“高级”选项卡下,点击…

    other 2023年6月27日
    00
  • FAT32与NTFS的区别 fat32与ntfs有什么区别

    FAT32与NTFS是常见的两种文件系统,分别用于存储和管理数据。它们有以下主要区别: 文件大小与分区大小限制 FAT32支持最大文件大小为4GB,同时也有分区大小限制,最大分区大小为2TB,但是如果使用Windows操作系统格式化磁盘则限制为32GB。而NTFS支持更大的文件和分区大小,最大文件大小为16EB,最大分区大小为256TB。 示例1:如果您需要…

    other 2023年6月27日
    00
  • java property配置文件管理工具框架过程详解

    Java Property 配置文件管理工具框架是 Java 语言中用于管理配置文件的一种工具框架。本攻略将详细讲解使用该框架的过程,包含如下内容: 安装 Java Property 配置文件管理工具框架 配置文件的定义和使用 代码示例:读取配置文件 代码示例:写入配置文件 接下来将详细介绍这些内容。 安装 Java Property 配置文件管理工具框架 …

    other 2023年6月25日
    00
  • C语言入门篇–局部全局变量的作用域及生命周期

    C语言入门篇–局部全局变量的作用域及生命周期 一、作用域及生命周期概述 在C语言中,变量是程序的重要组成部分,变量分为局部变量和全局变量。要了解变量的作用域及生命周期,需要先知道它们的含义。 1.1 作用域 作用域指的是变量在程序中能够被访问的范围。一般来说,在一个代码块内定义的变量只能在该代码块内被访问,这种变量称为局部变量。而在代码块外被定义的变量则为…

    other 2023年6月27日
    00
  • snowflakeid生成器

    snowflakeid生成器 什么是snowflakeid? Snowflakeid是Twitter的一个分布式唯一 ID 生成器,由于其高效和可靠性,已被广泛应用于许多领域的分布式系统中。它是一个64位整数,可以用于给分布式系统中的每一个数据记录生成唯一的标识符。 Snowflakeid 根据时间戳、数据中心 ID 和机器 ID 生成唯一 ID。其中,时间…

    其他 2023年3月28日
    00
  • swift中延迟执行

    Swift中延迟执行的完整攻略 在Swift中,我们可以使用延迟执行来推迟代码的执行,这在某些情况下非常有用。本攻略将详细介绍Swift中延执行的方法和示例。 延迟方法 Swift中有两种方法可以实现延迟执行: 使用DispatchQueue的asyncAfter方法 使用DispatchWorkItem的perform方法 方法一:使用DispatchQu…

    other 2023年5月9日
    00
  • 详解Javascript 中的 class、构造函数、工厂函数

    详解Javascript 中的 class、构造函数、工厂函数 1.构造函数 在JavaScript中,通过构造函数的方式来创建一个对象是非常常见的。构造函数可以通过使用关键字function和this来定义。 示例: function Person(name, age) { this.name = name; this.age = age; } let p…

    other 2023年6月26日
    00
  • C# 窗体(登录界面)

    概述 在C#中,我们可以使用窗体来创建用户界面。本文将为您提供一份完整攻略,介绍如何创建一个登录界面,并提供两个示例说明。 创建C#窗体登录界面的步骤 步骤1:创建新项目 在创建C#窗体登录界面之前,我们需要先创建一个新项目。可以使用以下步骤来创建新项目: 打开Visual Studio。 选择“File”菜单,然后选择“New”选项。 在“New Proj…

    other 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部