【高并发趣事三】——双重检查锁定与延迟初始化

简介: 【高并发趣事三】——双重检查锁定与延迟初始化

一、引言


在JAVA多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的 开销。双重检查锁定就是延迟 初始化技术。


二、双重检查锁定的由来


在jav进程中,有时候可能 需要推迟一些高开销对象的初始化操作,并且只有在使用这些对象时才进行初始化,此时,程序员可能会采用延迟初始化。还有一个经典的使用场景就是单利模式下的,为了提高性能 ,采用双重检查锁定模式。但是在使用的过程中我们需要一些技巧,否则很容易出现问题。


20200723171256576.png

上面代码在多线程环境下,我们很容易出现问题,所以改进代码。


20200723171355498.png

由于对getInstance()方法做了同步处理,synchronized将导致性能的开销。如果 getInstance()方法被多个线程频繁调用,将会导致程序执行性能下降。因此,为了提高性能,聪明的程序员想出了一个很好技巧: 双重检查锁定(DCL).继续优化代码


20200723171638684.png

这段代码看起来非常完美,但是这是一个错误的优化,在线程执行到第4行代码的时候,代码渠道instance不为null时,instance引用对象有可能还没有完成初始化。


三、 问题的源


在第七行代码,创建对象时候,我们可以将这一行代码进行分解为下面的伪代码。


20200723172017976.png


这就是我们JVM类加载的三个过程的抽象,如果我们非常熟悉类加载过程,我们应该会很清楚上面的三行伪代码的意思。


为什么将第七行代码拆开来说看呢,因为这三个过程可能会发生指令重排,发生指令重排后可能的执行顺序为:

20200723172439876.png


发生这样的指令重排完全符合规则,因为它重排以后保证了 单线程内程序的执行规则。

这样的执行顺序,在多线程的环境下,就会出现问题了,线程B将看到一个没有初始化的对象。


2020072317273381.png


四、解决方案


通过上面分析,我们知道了问题的原因是指令重排造成的,具体来说是上面的2和3发生重排导致,所以 我们解决问题的关键就是怎么解决重排的问题,下面两个思路


1、不允许2和3重排

2、允许2和3发生重排序,但是不允许其他线程看到这个重排序


基于volatile的解决方案


20200723173217943.png


当声明对象的引用为volatile后,上面的伪代码中的2和3指令之间的重排序在多环境中将会被禁止。


基于类的初始化的解决方案


JVM在类的初始化阶段, 会执行累点 初始化。在执行类的初始化期间,JVM会获取一个锁。这个锁可以同步多个线程对同一个类的初始化。基于这个特性,可以实现另一种线程安全的初始化方案。

20200723174937769.png

假设两个线程并发执行getInstance()方法,下面是执行示意图:


20200723175038959.png



这个方案的实质是,允许2和3重排序,但不允许非构造线程(B线程) 看到这个重排序。

目录
相关文章
|
存储 Java 编译器
【高并发趣事二】——JMM及程序中的幽灵
【高并发趣事二】——JMM及程序中的幽灵
67 0
【高并发趣事二】——JMM及程序中的幽灵
【高并发趣事一】——Amdahl(阿姆达尔定律)与Gustafson(古斯塔夫森定律)
【高并发趣事一】——Amdahl(阿姆达尔定律)与Gustafson(古斯塔夫森定律)
245 0
【高并发趣事一】——Amdahl(阿姆达尔定律)与Gustafson(古斯塔夫森定律)
|
SQL 开发框架 缓存
TPL Dataflow组件应对高并发,低延迟要求
2C互联网业务增长,单机多核的共享内存模式带来的排障问题、编程困难;随着多核时代和分布式系统的到来,共享模型已经不太适合并发编程,因此actor-based模型又重新受到了人们的重视。
TPL Dataflow组件应对高并发,低延迟要求
|
4月前
|
Java
在高并发环境下,再次认识java 锁
在高并发环境下,再次认识java 锁
36 0
|
4月前
|
消息中间件 NoSQL Java
Java高级开发:高并发+分布式+高性能+Spring全家桶+性能优化
Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师之路
|
11天前
|
缓存 负载均衡 Java
Java高并发性能指标
Java高并发是指在Java编程环境中,系统能够同时处理大量并发请求或操作的能力。这里的“高”强调的是并发处理的数量级较大,需要系统能够有效地管理多个并发的执行单元,如线程或进程,以确保它们能够高效且正确地执行。
11 0
|
16天前
|
JavaScript Java 测试技术
基于Java的高并发慕课网的设计与实现(源码+lw+部署文档+讲解等)
基于Java的高并发慕课网的设计与实现(源码+lw+部署文档+讲解等)
23 2
|
4月前
|
Java Go C语言
高并发时代到底是Go还是Java?
作为一名用过Java和Go开发过微服务架构程序的在校学生的角度思考,本文将从以下几个方便来讲述Go和Java的区别。
|
4月前
|
Java 数据库连接 微服务
Java程序员必学知识:高并发+微服务+数据结构+Mybatis实战实践
BATJ最全架构技术合集:高并发+微服务+数据结构+SpringBoot 关于一线互联网大厂网站的一些特点:用户多,分布广泛、大流量,高并发、海量数据,服务高可用、安全环境恶劣,易受网络攻击、功能多,变更快,频繁发布、从小到大,渐进发展、以用户为中心。 如果你工作中够仔细,你会发现这些特点跟高并发、分布式、微服务、Nginx这些技术密切相关的,是因为只要你的公司在上升,用户量级都会与日俱增,高性能、高并发的问题自然避免不了,话不多说往下看。
|
4月前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)

热门文章

最新文章