单例模式你真的懂了吗?


单例模式:某个类,在进程中只能有一份实例
单例模式分为: 饿汉模式和懒汉模式

饿汉模式

class Singleton {
    //饿汉模式
    private static Singleton ins = new Singleton();
    //为什么要设为静态?
    //因为属于类的变量,我们要想只要类一加载,就会创建。
	//不使用行不行?
	//不可以,因为就不属于类了,就需要通过创建实例,但是我们私有化了构造,所以不行。
    private Singleton() {
        ;//只能创建一个实例的决定性因素在此构造方法是私有的
    }
    //获取唯一实例
	 public static Singleton getIns() {
        return ins;
    }
}
class Main{
    public static void main(String[] args) {
        Singleton singleton1=new Singleton();//当我们去创建的时候就报错了!
        Singleton singleton2=Singleton.getIns();//这是正确的
    }
}

饿汉不会导致线程安全问题

懒汉模式

class Singletonlazy{
    //懒汉模式

   private static volatile  Singletonlazy Instance=null;//懒汉模式不着急去new,等程序需要才去new
    private Singletonlazy(){
        ;
    }
    public static Object obj=new Object();//定义一个锁对象
    
    public static Singletonlazy getInstance (){//获取唯一实例

        //这里为什么套两个if ?
        //第一个if判断是否要加锁,如果对象有了就不必加锁了
        //第二个if判断是否要创建对象
        if(Instance==null){
            synchronized (obj){
                if(Instance==null){
                
                    Instance=new Singletonlazy();//懒汉模式下,不能保证唯一性,所以加锁。 
                }
                
            }

        }
        return Instance;
    }
}
class Main{
    public static void main(String[] args) {
        Singletonlazy p1= Singletonlazy.getInstance();
        Singletonlazy p2= Singletonlazy.getInstance();
        System.out.println(p1==p2);//true

    }

上述代码中:Instance=new Singletonlazy();可能会发生指令重排序
注:当指令重排序后new操作执行顺序:创建内存->内存地址赋给引用->调用构造方法。
当我们有一个t1线程正在执行:创建内存->内存地址赋给引用时,突然调度给t2线程,t2线程执行时不为null,return走后执行某些操作时,因为我们还没调用构造方法赋值会导致出现问题。(小概率极端情况)
解决办法给引用添加volatile,加上后不优化了,也就不会导致指令重排序也保证了内存可见性问题,加锁也可保证了内存可见性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值