问题:Java中,在不使用synchronizedlock的情况下如何实现线程安全的单例模式?

原理:

本文给出三种思路,它们本质上都是借助ClassLoader线程安全的特点。原理部分在实现下详细讨论。

解答:

思路一:

使用静态内部类。

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

private Singleton () {}

public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

Java的JVM中类的初始化是由ClassLoader完成的,它本身就是线程安全。

思路二:

使用枚举

1
2
3
4
public enum Singleton {
INSTANCE;
public void nullMethod() {
}

Java的枚举类型本身也是使用static final类修饰每一个枚举项。

思路三:

饿汉模式

1
2
3
4
5
6
7
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}

静态类型成员变量instance在初始化时保存了Singleton的实例,Singleton类的初始化由ClassLoader负责,由于ClassLoader线程安全机制,因此创建Singleton类的过程也是线程安全。

本文给出三种思路,它们本质上都是借助ClassLoader线程安全的特点。不幸的是,ClassLoader中的loadClass在加载类是也是用synchronized关键字。于是,我们并没有不使用synchronized的情况下实现单例模式。

可能有人说,使用CAS方法来替代锁方案不就可以了吗?但事实上,CAS的实现本质上也是锁的思想。因此,本题严格地说无解。

完。