Java单例设计模式

//单例模式的两种实现方式  懒汉式和饿汉式
/*这两种实现,在单线程的模式下,也不会出现线程安全的问题,但是如果在多线程的情况下,就可能会出现多线程的安全问题
* 改进:双重校验锁 volatile:易变的 动荡的 反复无常的
* 第一次判断singleton是否为null是为了避免singleton已经创建的情况下 避免进入同步代码块 提升效率
*  第二次判断singleton是否为null是为了是为了避免并发情况下A线程经过第一次判断 进入同步代码块
*  此时B线程也经过判断准备进入同步代码块 但是发现同步锁已经被抢占 等待 A线程 释放后B线程进入同步代码块
*  发现此时singleton不为空,所以就不会创建新的对象了。 第二次的判断是很有必要的
*  TODO 既然有了Synchronized同步对象锁关键字作为限制 为什么还要加入Volatile呢
*  Volatile可以保证可见性和有序性,不能保证原子性 同时保证JVM对指令不会重新排序
*  这一点非常关键,对象的创建不是一步完成的,是一个符合操作,需要3个指令
*  singleton = new Singleton()
*  指令1:获取singleton对象的内存地址
*  指令2: 初始化singleton对象
*  指令3: 将这块内存地址,指向引用变量singleton
*  那么这样我们就可以理解,为什么要加入Volatile关键字了。由于Volatile禁止JVM指令进行重新排序
*  所以创建对象的过程依然是1,2,3
*  但是如果没有Volatile关键字,假设线程A正常创建一个实例,那么执行的顺序可能是 2,1,3
 *  当执行到指令1的时候,线程B执行getInstance()方法,获取到的,可能是对象的一部分,或者是不完整的对象
 *  程序会报异常信息
 *  */
class Singleton{//volatile可以保证有序性和可见性 不能保证原子性,所以才和synchronized配合使用
    private volatile static Singleton singleton;
    private Singleton() {//构造方法私有化是为了确保该类的唯一对象实例仅能通过get方法获取
    }
    public static Singleton getSingleton(){
        if (singleton == null) {//该if判断是为了减少每次都上锁的开销
            synchronized (singleton){
                if (singleton == null) {//为了防止A出锁 B进入锁后重复创建对象
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值