instance = new Singleton() 的代码可能被拆分为以下伪步骤(允许重排序):memory = allocate(); // 分配内存
instance = memory; // 引用指向内存地址(此时对象未初始化)
ctorInstance(memory); // 初始化对象若线程A执行到第二步时,线程B可能通过第一次判空获得未初始化的实例,导致程序错误
volatile 修饰实例变量:通过内存屏障禁止指令重排序,确保初始化完成后再赋值 15volatile:避免指令重排序问题,确保可见性 检查阶段 | 作用 | 技术原理 |
|---|---|---|
第一次判空 | 无锁快速判断,减少锁竞争 | 读多写少场景的性能优化 1 66 |
第二次判空 | 同步块内确认单例唯一性 | 防止多线程重复初始化 15 23 |
volatile | 禁止指令重排序,解决“半初始化”问题 | 内存屏障与可见性保障 15 19 |
通过两次判空与 volatile 的配合,DCL在多线程环境下实现了性能与安全的平衡,但需注意其适用条件与潜在风险。在实际开发中,应根据具体场景选择更简洁或更安全的替代方案。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicReference;
public class DatabaseConnectionPool {
// 使用 volatile 修饰实例变量,禁止指令重排序
private static volatile DatabaseConnectionPool instance;
// 连接池对象(示例中简化实现)
private final AtomicReference<Connection> connectionPool;
// 私有构造函数,防止外部实例化
private DatabaseConnectionPool() {
this.connectionPool = new AtomicReference<>(createConnection());
}
// 创建数据库连接(简化实现)
private Connection createConnection() {
try {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
} catch (SQLException e) {
throw new RuntimeException("Failed to create database connection", e);
}
}
// 获取数据库连接池实例(DCL 实现)
public static DatabaseConnectionPool getInstance() {
// 第一次判空:无锁快速判断,减少锁竞争
if (instance == null) {
synchronized (DatabaseConnectionPool.class) {
// 第二次判空:防止重复初始化
if (instance == null) {
instance = new DatabaseConnectionPool();
}
}
}
return instance;
}
// 获取连接(简化实现)
public Connection getConnection() {
return connectionPool.get();
}
// 释放连接(简化实现)
public void releaseConnection(Connection connection) {
// 示例中未实现具体逻辑
}
}
//代码解析
//volatile 修饰实例变量:
//确保 instance 的可见性,并禁止指令重排序,避免“半初始化”问题。
//第一次判空:
//无锁快速判断 instance 是否已初始化,减少锁竞争,提升性能。
//同步块与第二次判空:
//多个线程可能同时通过第一次判空进入同步块竞争锁。第二次判空确保仅首个线程初始化 instance,后续线程直接返回已存在的实例。
//延迟初始化:
//连接池对象在首次调用 getInstance() 时创建,避免系统启动时的资源浪费原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。