问题1:单例模式在多线程环境下的lazy模式为什么要加两个if(instance == null)?
回答1:第一层 if (instance == null)是为了减少线程对同步锁锁的竞争,第二层if(instance==nul)是保证单例。即
(1)if (instance == null) 的懒汉式多线程下是不安全的;
(2)synchronized/lock + if (instance == null) 的懒汉式多线程下是安全的;
(3)if (instance == null) + synchronized + if (instance == null) 的懒汉式在(2)的情况下减少对同步锁的竞争,提高效率。
问题2:如回答1,既然第二种方式已经看保证线程安全了,为什么需要从第二种方式变为第三种方式?或者为什么要使用双层同步锁?或者第三种方式 if (instance == null) + synchronized + if (instance == null) 的懒汉式是如何减少对同步锁的竞争?
回答2:如果使用第二种方式,即第三种方式没有第一层if (instance == null) ,每次调用newInstance()方法都会先synchronized/lock 然后判断 if (instance == null) ,对于一共 n 次调用newInstance静态方法,对于第二层的 if (instance == null),只有第一次创建在为true,后面都是为false,不需要再次新建了,因为是单例,所以对于后面的 n-1 次调用newInstance,都是先获取到同步锁,然后 if(instance==null)为false,这样白白的消耗性能,后面的 n-1 次,每个线程辛辛苦苦的获取到的同步锁,发现没卵用,还不如不要获取同步锁,尝试的解决方法有两个:
① synchronized/lock + if (instance == null) 变为 if (instance == null) + synchronized/lock,但是这样修改后,第一批进入的线程破坏单例模式。
② synchronized/lock + if (instance == null) 变为 if (instance == null) + synchronized/lock + if (instance == null),在保证线程安全的第二种方式前面加一层 if (instance == null)判断,变为双层检测,这样在保证单例的情况下,提高效率,减少性能浪费。
问题3:为什么说刚才的第一种方式 synchronized/lock + if (instance == null) 变为 if (instance == null) + synchronized/lock ,无法保证第一批进入的线程仅创建一个对象?
回答3:虽然 if (instance == null) 实现后面调用阻止进入,提高了效率,同时 synchronized/lock 保证内部新建单例的原子性,但是由于没有内层 if (instance == null) ,第一批进入的每一个线程都会创建一个对象,破坏单例模式