Java单例模式深度解析:线程安全与性能优化
需积分: 0 75 浏览量
更新于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 上传
2023-12-08 上传
2024-04-24 上传
2024-05-08 上传
2023-04-29 上传
2023-11-10 上传
2023-10-15 上传
苹果虾丸
- 粉丝: 3
- 资源: 871
最新资源
- ***+SQL三层架构体育赛事网站毕设源码
- 深入探索AzerothCore的WoTLK版本开发
- Jupyter中实现机器学习基础算法的教程
- 单变量LSTM时序预测Matlab程序及参数调优指南
- 俄G大神修改版inet下载管理器6.36.7功能详解
- 深入探索Scratch编程世界及其应用
- Aria2下载器1.37.0版本发布,支持aarch64架构
- 打造互动性洗车业务网站-HTML5源码深度解析
- 基于zxing的二维码扫描与生成树形结构示例
- 掌握TensorFlow实现CNN图像识别技术
- 苏黎世理工自主无人机系统开源项目解析
- Linux Elasticsearch 8.3.1 正式发布
- 高效销售采购库管统计软件全新发布
- 响应式网页设计:膳食营养指南HTML源码
- 心心相印婚礼主题响应式网页源码 - 构建专业前端体验
- 期末复习指南:数据结构关键操作详解