Dubbo-双检查锁

 首先看一下类的初始化条件:

  • T是一个类,而且一个T类型的实例被创建;
  • T是一个类,且T中声明的一个静态方法被调用;
  • T中声明的一个静态字段被赋值;
  • T中声明的一个静态字段被使用,而且这个字段不是一个常量字段;
  • T是一个顶级类(top level class,见java语言规范的§7.6),而且一个断言语句嵌套在T内部被执行。

静态内部类实现单例, 在调用getInstance()方法时,使用到了内部类的静态成员变量,所以会执行内部类的初始化,实现了静态域的延迟加载(或者延迟初始化)。

双检查锁实现了(实例域 的延迟初始化,也就是对象的非静态域。)

最好的方式 是使用枚举实现单例模式,因为可以避免反射供给和解决序列化之后不相等的问题,

解决反射攻击是因为 jvm在判断类型为ENUM的时候回直接抛出异常,枚举的反序列化并不是通过反射实现的.

一般情况下,不建议使用懒汉方式(有两种一个是最基本的,另一个是线程安全的),建议使用饿汉方式。 只有在要明确实现 lazy loading 效果时,才会使用静态内部类单例方式。 如果涉及到反序列化创建对象时,可以尝试使用枚举方式实现的单例。 如果有其他特殊的需求,可以考虑使用双检锁方式实现的单例。

双检查锁的使用时避免成员变量共享时出现的线程安全问题,在dubbo源码中我们可以看到很多场景运用的都是双检查锁,但是都是在方法内部,对于局部变量使用双检查锁,而Java内存模型中,我们知道Java栈,本地方法栈,程序计数器都是线程私有的,我们执行的方法,都是栈桢入栈操作,也就是进入到虚拟机栈(Java栈)所以都是线程私有的不存在线程安全问题,所以使用是没有问题的。dubbo中使用的目的不是延迟初始化,使用的目的就是我们使用了缓存的前提下,只要缓存中有的时候我们尽量去缓存中去取,只在缓存中没有的时候再去创建或者数据库中获取数据,使用双检查锁可以避免缓存的多次创建和频繁的创建或者链接数据库(在redis并发的场景中我们可以使用。)

参考链接:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值