CAS非锁怎样实现单例的一个缺陷

发布时间:2021-12-18 13:35:53 作者:柒染
来源:亿速云 阅读:135

这期内容当中小编将会给大家带来有关CAS非锁怎样实现单例的一个缺陷,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

今天我们要说的是,无锁实现单例模式,以及这种 CAS 实现的单例的缺点。

传统的 7 种单例模式大致如下:

CAS非锁怎样实现单例的一个缺陷

它们都是用锁来实现。但是如果在面试过程中面试官问你如何使用非锁来实现一个单例呢?

答案就是下图这种实现。

CAS非锁怎样实现单例的一个缺陷

这是网上一位大牛的实现,他的这种非锁 CAS 实现的单例,挺好的。但是平时可能没有人使用,比用锁稍微复杂了一点,这也是为什么没有被列入单例模式的 7 大写法之中了。我在他的基础上,也就是他的构造方法里添加了两行代码。

CAS非锁怎样实现单例的一个缺陷

我主要是想看看它到底是实例化了几次。加上这两行代码,可以方便我观察控制台,和统计实例化的总次数。

然后,我的测试代码如下:

CAS非锁怎样实现单例的一个缺陷

关于 CountDownLatch 有不会的,可以看我的《CountDownLatch 压测教程》一文。

我这里主要是想压测一下,非锁 CAS 单例模式是否会创建多次对象。

运行上面的 main 方法,我截图了一下最终结果。

CAS非锁怎样实现单例的一个缺陷

CAS 以原子方式更新内存中相应的值,从而保证了多线程环境下共享变量更新操作的同步。的确,这种方式可以保证每次调用getInstance() 方法得到的一定是同一个实例。因此,从功能实现的角度来看,这种做法达到了预期的目的。但是,经过分析和测试,却发现这种方式有一些预期之外的弊病:可能会创建不止一个对象。

CAS 本身的操作的确是原子方式,但是包装 CAS 指令的方法并非是全程同步的,当然,在包含 CAS 指令的方法开始调用之前,参数计算过程中更不是互斥执行的!当一个线程测试 instance.get() == null 得到 true 之后,往下它就一定会调用 new Singleton()。因为,这并不是 CAS 方法的一部分,而是它的参数。在调用一个方法之前,需要先将其参数压入栈,当然,需要先计算参数表达式,因此,产生如上结果也就不难预料了。

CAS 与锁的区别在于,它是非阻塞的,也就是说,它不会去等待一个条件,而是一定会去执行,结果要么成功,要么失败。它的操作时间是可预期的。如果我们的目的是一定要成功执行 CAS,那就需要不断循环执行直至成功,同时,建立在成功预期之上大量的准备工作是值得的,但是,如果我们不希望操作一定成功,那为成功操作而做的准备工作就浪费掉了。

上述就是小编为大家分享的CAS非锁怎样实现单例的一个缺陷了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. 单例的实现方式
  2. 双重校验锁实现单例模式(对象单例,线程安全)

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

cas java

上一篇:为什么Java中的Collection类都继承了抽象类还要实现抽象类的接口

下一篇:如何进行springboot配置templates直接访问的实现

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》