java单例模式 懒汉式(双重检查锁)
/** * 懒汉式 方式6 双重检查锁 */publicclassSingletonLazy{// 1、私有构造方法privateSingletonLazy(){}// 2、在成员变量位置声明一个静态对象privatestaticvolatileSingletonLazyinstance;// 关键字volatile禁止指令重排序确保绝对安全// 3、对外提供静态方法获取唯一实例publicstaticSingletonLazygetInstance(){if(instancenull){// 提升性能第一次判断若instance不为空不进入抢锁阶段直接返回实例synchronized(SingletonLazy.class){if(instancenull){// 确保安全第二次判断抢到锁后再次判断是否为nullinstancenewSingletonLazy();}}}returninstance;}}synchronized (SingletonLazy.class) 是干什么的作用 这是一个互斥锁排他锁。因为 getInstance 是一个 static 方法它不属于任何对象实例而是属于类本身。所以需要锁住 SingletonLazy.class 这个类对象。比喻想象 synchronized 花括号 { … } 包裹的代码块是一个试衣间而 SingletonLazy.class 是这个试衣间唯一的钥匙。不管外面有多少人线程想进去同一时间只有一个人能拿着钥匙进去。其他人如果没有抢到钥匙就必须在门口排队等待Block直到里面的人出来并归还钥匙。2. 为什么抢到锁了还要做第二次判断**疑问“既然线程 A 进去了线程 B 就进不去那线程 A 放心大胆地创建不就行了吗”答案为了防止“漏网之鱼”。模拟一个多线程并发的场景就明白了场景还原假设有两个线程线程 A 和 线程 B同时调用 getInstance()且此时 instance 为 null。第一步关键线程 A 执行到第 11 行 if (instance null)判断为 true需要创建。同时线程 B 也执行到第 11 行因为它还没被锁住它看到的 instance 也是 null判断也为 true。结果 A 和 B 都通过了第一层关卡来到了 synchronized 门外。第二步抢锁线程 A 动作快抢到了锁进入了 synchronized 块内部。线程 B 慢了一步被挡在门外进入阻塞等待状态。注意 此时线程 B 已经通过了第一个 if它只是在等锁而不是被第一个 if 挡回去。第三步A 创建对象线程 A 在锁内部执行 instance new SingletonLazy();。对象创建完毕instance 不再是 null。线程 A 释放锁离开。第四步B 的灾难锁被释放了线程 B 终于拿到了锁进入了 synchronized 块内部。如果没有第二次判断 线程 B 会直接执行 new SingletonLazy()。后果 虽然 A 已经创建了一个对象但 B 又创建了一个单例模式失效了变成了“双例”。第五步B 的救赎 - 第二次判断因为有了第 13 行的 if (instance null)。线程 B 进门后虽然它之前在门外看到的是 null但它进门后再看一眼发现 instance 已经被 A 初始化了不为 null。结果 线程 B 放弃创建直接退出。总结第一次判断 (if outside) 是为了性能。一旦对象创建好了后面的线程根本不需要排队抢锁直接拿走对象即可。第二次判断 (if inside) 是为了安全。防止在多线程并发的极端情况下两个线程同时通过了第一层检查导致重复创建对象。补充为什么instance 变量必须加上 volatile 关键字。在 Java 高并发环境下这段代码不加volatile关键字有一个隐患。// 必须加 volatileprivatestaticvolatileSingletonLazyinstance;原因 new SingletonLazy() 这个操作在计算机底层不是原子性的它分三步分配内存。初始化对象。将 instance 指向这块内存。如果没有 volatileCPU 可能会指令重排序比如变成 1 - 3 - 2。如果在执行完 1 和 3此时 instance 已经不为 null但对象还没初始化好时另一个线程来了它在第一次判断时发现 instance 不为 null直接拿去用了。结果就是拿到了一个半成品对象程序报错。volatile 的作用就是禁止指令重排序保证绝对安全。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2477296.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!