public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
去掉第一个判断为空:即懒汉式(线程安全),这会导致所有线程在调用getInstance()方法的时候,直接排队等待同步锁,然后等到排到自己的时候进入同步处理时,才去校验实例是否为空,这样子做会耗费很多时间(即线程安全,但效率低下)。
去掉第二个判断为空:即懒汉式(线程不安全),这会出现 线程A先执行了getInstance()方法,同时线程B在因为同步锁而在外面等待,等到A线程已经创建出来一个实例出来并且执行完同步处理后,B线程将获得锁并进入同步代码,如果这时B线程不去判断是否已经有一个实例了,然后直接再new一个。这时就会有两个实例对象,即破坏了设计的初衷。(即线程不安全,效率高)
双重校验的目的:除了第一次实例化需要进行加锁同步,之后的线程只要进行第一层的if判断不为空即可直接返回,而不用每一次获取单例都加锁同步,因此相比前面两种懒汉式,双重检验锁更佳。(双重校验锁结合了 两种懒汉式 的优点)