Singleton Pattern
Conceptual
保证一个类只有一个实例
为该实例提供一个全局访问节点
无论何时调用该方法,它总是会返回相同的对象
Pros & Cons
Pros
- 你可以保证一个类只有一个实例,提供了一个指向该实例的全局访问节点
- 仅在首次请求单例对象时对其进行初始化
Cons
- 违反了单一职责原则。 该模式同时解决了两个问题
- 单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等
- 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象
- 单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象。 由于单例类的构造函数是私有的, 而且绝大部分语言无法重写静态方法, 所以你需要想出仔细考虑模拟单例的方法。 要么干脆不编写测试代码, 或者不使用单例模式
Code
1 | public class ThreadSafeSingleton(){ |
FAQ
不加锁的问题
- 多线程情况下就不再是单例Object
synchronized直接修饰方法的问题
- 每次访问方法都会加锁,性能开销大
双重检查锁(double checked locking)
- 针对对象加synchronized锁(低性能损耗下,返回单例Object)
- 对象必须加Volatile修饰(处理重排序问题)
Volatile
new 方法编译后实际会出现
- 分配内存空间
- 将对象指向刚分配的内存空间
- 初始化对象
多个操作,即使synchronized已经加了锁,在多线程访问情况下,可能访问获得到的是一个初始化未完成的对象。
因此,添加Volatile
关键字禁止重排序,所有的write都发生在read操作前,获取完整对象