创建一个单例模式有多难?
春节过完了,家里蹲久了,该刷的剧不该刷的剧都已经mission complete了。唯独翻开夹着小纸条的书本的时候,想起了信誓旦旦曾经发过的誓言,庆幸自己没有附带些恶毒的惩罚措施。
时间久了,头发没长多少,对基本的知识日渐生疏,推荐大家一本学习Java的好书,“达摩院”的《Java开发手册 华山版》,在阿里云只要0.01元,买了不吃亏,不怕垫桌角。
问题来了,看到这么一道题,“你会写一个单例吗?”
太简单了,简直侮辱智商...
public class Singleton {
private static Singleton uniqueSingleton;
private Singleton() {
}
public Singleton getInstance() {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
return uniqueSingleton;
}
}
等等... 既然这么问了,一定有陷阱,啊,多线程,来加一个锁
public class Singleton {
private static Singleton uniqueSingleton;
private Singleton() {
}
public synchronized Singleton getInstance() {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
return uniqueSingleton;
}
}
这样性能好像有点问题,原本第一次才需要判断是否初始化,现在次次都要加锁, 敲豆麻袋... 引入 “双重检查锁”(double checked locking)吧
public class Singleton {
private static Singleton uniqueSingleton;
private Singleton() {
}
public Singleton getInstance() {
if (null == uniqueSingleton) {
synchronized (Singleton.class) {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
}
这样是不是就完美了呢?答案 “并不是”
引入《开发手册》原文推荐
在并发场景下,通过双重检查锁(double-checked locking)实现延迟初始化的优化 问题隐患(可参考 The "Double-Checked Locking is Broken" Declaration),推荐解决方案中较为 简单一种(适用于 JDK5 及以上版本),将目标属性声明为 volatile 型。
修改一下
public class Singleton {
private volatile static Singleton uniqueSingleton;
private Singleton() {
}
public Singleton getInstance() {
if (null == uniqueSingleton) {
synchronized (Singleton.class) {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
}
使用了volatile关键字后,重排序被禁止,所有的写(write)操作都将发生在读(read)操作之前。
参考资料:
https://www.cnblogs.com/xz816111/p/8470048.html
完美,睡觉了。