0

0

在Java中如何实现线程安全的单例模式_Java并发单例实现思路解析

P粉602998670

P粉602998670

发布时间:2026-02-01 06:53:08

|

749人浏览过

|

来源于php中文网

原创

饿汉式单例天然线程安全,因static字段在类加载阶段由JVM同步初始化,确保INSTANCE唯一且无竞态;但存在提前创建、无法传参等问题。

在java中如何实现线程安全的单例模式_java并发单例实现思路解析

为什么饿汉式单例天然线程安全

因为 static 字段在类加载阶段就完成初始化,而类加载过程由 JVM 保证同步,多个线程并发触发类加载时,只会有一个线程执行 clinit 方法,其余阻塞等待。这意味着 INSTANCE 在首次访问前已构造完毕,不存在竞态条件。

但要注意:实例会在类加载时立即创建,即使后续从未被使用,造成资源浪费;且无法传递构造参数。

public class EagerSingleton {
    private static final EagerSingleton INSTANCE = new EagerSingleton();

    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

双重检查锁定(DCL)必须加 volatile 关键字

不加 volatile 会导致指令重排序问题:JVM 可能将对象引用赋值(instance = new Singleton())提前到构造函数执行完成前,使其他线程看到一个未初始化完成的对象,引发 NullPointerException 或诡异状态。

  • volatile 禁止重排序,并保证可见性
  • 第一次判空避免不必要的同步开销
  • 第二次判空防止多线程重复初始化
public class DclSingleton {
    private static volatile DclSingleton instance;

    private DclSingleton() {}

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

静态内部类方式兼顾延迟加载与线程安全

利用 JVM 类加载机制的天然同步特性:外部类加载时,内部类不会被加载;只有首次调用 Holder.INSTANCE 时,Holder 类才被加载并初始化 static 字段,此时 JVM 保证线程安全且只执行一次。

立即学习Java免费学习笔记(深入)”;

InsCode
InsCode

InsCode 是CSDN旗下的一个无需安装的编程、协作和分享社区

下载

这是推荐的写法——无同步开销、延迟加载、无需 volatile、支持构造参数(通过内部类构造器传入)。

public class HolderSingleton {
    private HolderSingleton() {}

    private static class Holder {
        private static final HolderSingleton INSTANCE = new HolderSingleton();
    }

    public static HolderSingleton getInstance() {
        return Holder.INSTANCE;
    }
}

枚举单例为何最难被破坏

反射攻击和反序列化漏洞在枚举面前基本失效:JVM 对枚举实例的创建有特殊限制,Enum.valueOf() 和反序列化逻辑都强制复用已有实例,无法通过反射调用私有构造器生成新实例(会抛出 java.lang.EnumException)。

但注意:枚举单例无法继承其他类(Java 枚举隐式继承 java.lang.Enum),若需扩展行为,得靠组合或接口实现。

public enum EnumSingleton {
    INSTANCE;

    public void doSomething() {
        // 实际逻辑
    }
}
真正容易被忽略的是:所有基于 new 的单例实现(包括 DCL 和内部类),一旦类被多次加载(如不同 ClassLoader),就会产生多个实例——单例性只在同一个类加载器内成立。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

69

2025.10.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1180

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

215

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2158

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

27

2026.01.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

546

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

210

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

20

2026.01.21

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.1万人学习

C# 教程
C# 教程

共94课时 | 8.1万人学习

Java 教程
Java 教程

共578课时 | 54.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号