单例模式深入理解

我们熟知的单例模式有两种一种饿汉式,另外一种是懒汉式

"饿汉式"单例模式,思想是利用空间换时间,实现比较简单

//单例饿汉式
public class T {
    //构造私有
    private T(){}
    //创建唯一的对象
    private static final T t = new T();
    //提供唯一的方式让外界获取
    public static T getInstance(){
        return t;
    }

    public static void main(String[] args) {
        // 这一种没有多线程安全问题
        for (int i = 1; i <= 100 ; i++) {
            new Thread(){
                @Override
                public void run() {
                    //我们通过hashCode() 来判断是不是同一个对象
                    System.out.println(T.getInstance().hashCode());
                }
            }.start();
        }
    }
}

效果如图(部分),这个单例模式不会出现线程安全问题

"懒汉式"单例模式:懒汉式单例模式的思想是利用时间换空间,会出现线程安全问题

public class W {
    //不管是饿汉式还是懒汉式,我们都需要构造私有化
    private W() {
    }

    //定义当前数据类型
    private static W w;

    //定义能够访问对象的方法
    public static W getInstance() {
        // 判断当前对象是否存在
        if (w == null) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 不存在创建出唯一的一个对象
            w = new W();
        }
        return w;
    }

    public static void main(String[] args) {
        for (int i = 1; i <= 100 ; i++) {
            new Thread(){
                @Override
                public void run() {
                    System.out.println(W.getInstance().hashCode());
                }
            }.start();
        }
    }
}

 以上是我们懒汉式的最原始的形态,我们通过测试,会发现,在多线程的情况下我们获得的并不是同一个对象;

之后我们通过我们的同步代码块来进行修改程序,第一次修改

 所以这时我们就引入了 锁的双重判断机制,就是在线程进入到锁内部的时候,再次判断对象是否存在.这样也可以提高我们的代码效率,也保证了在多线程下,创建出唯一的一个对象

 我们通过测试发现,多线程下也是同一个对象,当然这也就是我们所认为的比较标准的一种单例的书写模式

 

但是这个懒汉式单例模式隐含着问题的,就是我们再使用双重判断到时候,可能会出现"半初始化问题",所谓的半初始化就是我们在 new对象 的时候,另外一个线程进行赋值, 但是这个不会在高并发很小的时候出现,可能上百万次也不会出现.

那么为啥会出现上面的半初始化问题,这是因为我们的代码最终会被转成我们的汇编语言进行执行,那么这里面的有些指令在多线程多cpu的情况下就会发生一种叫指令重排序的优化,目的就是在不影响最后的结果的情况下,可以调换指令的执行顺序.

那么如果我们不想让我们的代码出现以上情况,就 需要在对象的引用前添加volatile关键字,来防止多线程多cpu情况下指令重排

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不不就不

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值