Java单例模式深度解析:线程安全与性能优化
需积分: 0 76 浏览量
更新于2024-09-01
收藏 139KB PDF 举报
性能优化",允许指令重排序,也就是这三步不一定按照顺序执行。在多线程环境下,如果步骤2和3发生了重排序,就会导致线程安全问题。具体来说,假设线程A执行到步骤1,发现`singleton`为`null`,于是进入同步代码块,但此时线程切换到了线程B,线程B同样执行到步骤1,由于`singleton`仍为`null`,线程B也会进入同步代码块并创建一个新的实例。当线程A再次获得CPU时间片,它会跳过步骤2(因为线程B已经完成了),直接执行步骤3,这样就创建了两个`Singleton`实例,违反了单例模式的基本原则。
为了解决这个问题,Java引入了 volatile 关键字。volatile 可以禁止指令重排序,并确保所有线程看到的 `singleton` 始终是最新的。修改后的代码如下:
```java
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) { // 第一次检查
synchronized (Singleton.class) {
if (singleton == null) { // 第二次检查
singleton = new Singleton(); // 现在是安全的
}
}
}
return singleton;
}
}
```
现在,即使有指令重排序,线程B也无法看到未完全初始化的 `singleton`,因为 `volatile` 确保了线程可见性和禁止了重排序。
然而,随着Java内存模型的进一步发展,从Java 5开始,`Singleton`的饿汉式实现也成为了一种推荐的做法。这种方式在类加载时就完成了实例化,避免了多线程同步的问题:
```java
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
```
这种方式虽然看起来不是懒加载,但在Java中,类加载是线程安全的,因此这种实现方式是线程安全且高效的。
除此之外,枚举单例也是推荐的一种方式,它不仅简单,而且天然线程安全:
```java
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
```
这里,Singleton是一个枚举类型,只有一个INSTANCE实例,枚举在JVM中是天然单例的,不允许任何形式的子类化,因此保证了单例的唯一性。
Java中的单例模式有很多种实现方式,每种都有其适用场景和优缺点。理解这些实现方式以及它们背后的内存模型和并发原理对于编写高效、线程安全的代码至关重要。
2017-12-04 上传
2018-12-20 上传
2017-12-03 上传
点击了解资源详情
2021-01-20 上传
2013-06-03 上传
点击了解资源详情
点击了解资源详情
2012-12-07 上传
苹果虾丸
- 粉丝: 3
- 资源: 871
最新资源
- Raspberry Pi OpenCL驱动程序安装与QEMU仿真指南
- Apache RocketMQ Go客户端:全面支持与消息处理功能
- WStage平台:无线传感器网络阶段数据交互技术
- 基于Java SpringBoot和微信小程序的ssm智能仓储系统开发
- CorrectMe项目:自动更正与建议API的开发与应用
- IdeaBiz请求处理程序JAVA:自动化API调用与令牌管理
- 墨西哥面包店研讨会:介绍关键业绩指标(KPI)与评估标准
- 2014年Android音乐播放器源码学习分享
- CleverRecyclerView扩展库:滑动效果与特性增强
- 利用Python和SURF特征识别斑点猫图像
- Wurpr开源PHP MySQL包装器:安全易用且高效
- Scratch少儿编程:Kanon妹系闹钟音效素材包
- 食品分享社交应用的开发教程与功能介绍
- Cookies by lfj.io: 浏览数据智能管理与同步工具
- 掌握SSH框架与SpringMVC Hibernate集成教程
- C语言实现FFT算法及互相关性能优化指南