1. 参考资料
- 单例模式-伯乐在线
-
2. 知识点理解
- 定义:系统运行中有且仅有一个实例
- 示例代码:
public class Singleton {
private Singleton() {} //关键点0:构造函数是私有的
private static Singleton single = null; //关键点1:声明单例对象是静态的
private static object obj= new object();
public static Singleton GetInstance() //通过静态方法来构造对象
{
if (single == null) //关键点2:判断单例对象是否已经被构造
{
lock(obj) //关键点3:加线程锁
{
if(single == null) //关键点4:二次判断单例是否已经被构造
{
single = new Singleton();
}
}
}
return single;
}
}
- 注意点
- 构造函数必须为private
- 单例对象必须声明为静态:外部静态调用
- 构造单例对象之前要加锁(lock一个静态的object对象)
- 需要两次检测单例实例是否已经被构造,分别在锁之前和锁之后 Double Check lock
- 枚举类 Instance 实现单例,InstanceEnum.Instance调用
- 关键问题
- 为何要检测两次?有可能延迟加载或者缓存原因,造成构造多个实例,违反了单例的初衷。
- 构造函数能否公有化?不行,单例类的构造函数必须私有化,单例类不能被实例化,单例实例只能静态调用
- lock住的对象为什么要是object对象,可以是int吗?不行,锁住的必须是个引用类型。如果锁值类型,每个不同的线程在声明的时候值类型变量的地址都不一样,那么上个线程锁住的东西下个线程进来会认为根本没锁,相当于每次都锁了不同的门,没有任何卵用。而引用类型的变量地址是相同的,每个线程进来判断锁多想是否被锁的时候都是判断同一个地址,相当于是锁在通一扇门,起到了锁的作用。
转载于:https://my.oschina.net/u/3686885/blog/1834841