//final类不可继承
final public class Single {
//使用volatile修饰变量,禁止指令重排
private volatile static Single single = null;
public static Single create() {
//第一次验校
if (single == null) {
//同步代码块(类锁)
synchronized (Single.class) {
//第一次验校
if (single == null) {
single = new Single();
}
}
}
return single;
}
/**
* 私有构造函数,外部访问不了
*/
private Single() {
}
}
-
为什么要进行第一次判空
我们知道单例模式只有第一次执行create()方法的时候才会走synchronized 中的代码,后面再次访问的时候直接返回single 对象。如果说我们没有第一次验校,每一个线程都要走synchronized 中的代码,而每一次线程都要去拿到同步锁才能执行。在多线程的情况下每一个线程要拿到single 对象都要排队等待同步锁释放。因此第一次验校作用就是为了提高程序的效率。 -
为什么要进行第二次判空
举个例子:假如现在没有第二次验校,线程A执行到第一次验校那里,它判断到single ==null。此时它的资源被线程B抢占了,B执行程序,进入同步代码块创建对象,然后释放同步锁,此时线程A又拿到了资源也拿到了同步锁,然后执行同步代码块,因为之前线程A它判断到single ==null,因此它会直接创建新的对象。所以就违反了我们设计的最终目的。 -
变量为什么要加volatile关键字
请读者自行了解volatile的原理。 -
优缺点、使用场景
https://www.cnblogs.com/restartyang/articles/7770856.html