饿汉式单例模式
public class Singleton1{
/**一开始就创建了一个实例**/
private static Singleton1 instance = new Singleton1();
/**提供静态的公共方法,获得唯一实例**/
public static Singleton1 getInstance(){
return instance;
}
/**私有的构造方法**/
private Singleton1(){
}
}
懒汉式单例模式(已优化)
public class Singleton2{
private static Singleton2 instance = null;
/**提供静态的公共方法,获得唯一实例**/
public static Singleton2 getInstance(){
/**判空**/
if(instance==null){
/**若为空,上锁,其他线程在外面等待**/
synchronized(Singleton2.class){
/**再判一次空,以防等后面的线程进来之后直接创建一个新的实例**/
if(instance==null){
/**若为空,则new一个实例**/
instance = new Singleton2();
}
}
return instance;
}
}
/**私有构造方法**/
private Singleton2(){
}
}
以上的懒汉式,为什么要进行两次判空呢?懒汉式单例模式涉及并发的问题。
第一个判空,是判断当前的实例是否为空,若不为空的话,则进入准备创建一个新的实例,所以这时候必须用synchronized上锁,防止其他线程也判断为空进来创建实例,换言之它在准备要创建实例的时候不允许其他线程进来。接下来再判断一次空,是因为上锁之后可能其他线程在synchronized外面排队,等第一个实例创建完之后,其他线程进来了,如果这时候不判断实例是否为空就创建,就可能又创建一个实例,违背了单例模式了。
为什么synchronized放在第一个判空里面而不是放在方法声明?
请看一下代码:
/**提供静态的公共方法,获得唯一实例**/
/**由于使用synchronized会影响性能,若放在方法声明里,则会每次调用getInstance()获取实例的时候都上锁,导致性能降低**/
public static synchronized Singleton2 getInstance(){
}
若使用两次判空,把synchronized放到方法里面,通过第一个判空可减少了synchronized的执行次数。
/**提供静态的公共方法,获得唯一实例**/
public static Singleton2 getInstance(){
/**判空**/
if(instance==null){
/**若为空,上锁,其他线程在外面等待**/
synchronized(Singleton2.class){
/**再判一次空,以防等后面的线程进来之后直接创建一个新的实例**/
if(instance==null){
/**若为空,则new一个实例**/
instance = new Singleton2();
}
}
return instance;
}
}
本文深入探讨了饿汉式和懒汉式两种单例模式的实现方式,并重点解析了懒汉式单例模式中双重检查锁定的原理及其在并发场景下的应用。
2082

被折叠的 条评论
为什么被折叠?



