在高并发环境下,实现单例模式以确保线程安全,通常需要避免使用懒汉式单例(懒汉式单例在多线程环境下可能会创建多个实例),而采用饿汉式单例或者同步锁来保证实例的唯一性和线程安全。
以下是几种常用的实现方式:
### 饿汉式单例
饿汉式单例在类加载时就完成了实例的初始化,因此天生就是线程安全的。
```java
public class Singleton {
? ? private static final Singleton instance = new Singleton();
? ? private Singleton() {
? ? ? ? // 私有构造器
? ? }
? ? public static Singleton getInstance() {
? ? ? ? return instance;
? ? }
}
```
### 同步锁单例
如果需要懒加载(即在需要时才创建实例),可以使用同步锁来保证线程安全。
```java
public class Singleton {
? ? private static Singleton instance;
? ? private Singleton() {
? ? ? ? // 私有构造器
? ? }
? ? public static synchronized Singleton getInstance() {
? ? ? ? if (instance == null) {
? ? ? ? ? ? instance = new Singleton();
? ? ? ? }
? ? ? ? return instance;
? ? }
}
```
这里使用了 `synchronized` 关键字来同步 `getInstance` 方法,但这会带来性能开销,因为每次调用 `getInstance` 都需要进行同步。
### 双重检查锁定(Double-Checked Locking)
双重检查锁定是一种在实例未被创建时才同步的方法,它既实现了懒加载,又保证了线程安全。
```java
public class Singleton {
? ? private static volatile Singleton instance;
? ? private Singleton() {
? ? ? ? // 私有构造器
? ? }
? ? public static Singleton getInstance() {
? ? ? ? if (instance == null) {
? ? ? ? ? ? synchronized (Singleton.class) {
? ? ? ? ? ? ? ? if (instance == null) {
? ? ? ? ? ? ? ? ? ? instance = new Singleton();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return instance;
? ? }
}
```
注意,这里使用了 `volatile` 关键字来确保多个线程都能够正确处理 `instance` 变量。
### 使用内部静态类(Bill Pugh Singleton)
这种方式利用了Java类加载机制来保证线程安全,同时实现了懒加载。
```java
public class Singleton {
? ? private Singleton() {
? ? ? ? // 私有构造器
? ? }
? ? private static class Holder {
? ? ? ? private static final Singleton INSTANCE = new Singleton();
? ? }
? ? public static Singleton getInstance() {
? ? ? ? return Holder.INSTANCE;
? ? }
}
```
以上就是在高并发环境下保证单例模式线程安全的一些常用方法。选择哪种方式取决于具体的需求和场景。