Java并发编程吐血1个月总结最全面的100道面试题
moboyou 2025-06-08 18:49 39 浏览
目录
- 一、大部分人对Java并发仍停留在理论阶段
 - 二、中间件系统的内核机制:双缓冲机制
 - 三、百万并发的技术挑战
 - 四、内存数据写入的锁机制以及串行化问题
 - 五、片机制 + 分段加锁机制
 - 六、缓冲区写满时的双缓冲交换
 - 七、且慢!刷写磁盘不是会导致锁持有时间过长吗?
 - 八、内存 + 磁盘并行写机制
 - 九、为什么必须要用双缓冲机制?
 - 十、总结
 
这篇文章,给大家聊聊一个百万级并发的中间件系统的内核代码里的锁性能优化。
很多同学都对Java并发编程很感兴趣,学习了很多相关的技术和知识。比如volatile、Atomic、synchronized底层、读写锁、AQS、并发包下的集合类、线程池,等等。
一、对Java并发仍停留在理论阶段
很多同学对Java并发编程的知识,可能看了很多的书,也通过不少视频课程进行了学习。
但是,大部分人可能还是停留在理论的底层,主要是了解理论,基本对并发相关的技术很少实践和使用,更很少做过复杂的中间件系统。
实际上,真正把这些技术落地到中间件系统开发中去实践的时候,是会遇到大量的问题,需要对并发相关技术的底层有深入的理解和掌握。
然后,结合自己实际的业务场景来进行对应的技术优化、机制优化,才能实现最好的效果。
因此,本文将从笔者曾经带过的一个高并发中间件项目的内核机制出发,来看看一个实际的场景中遇到的并发相关的问题。
同时,我们也将一步步通过对应的伪代码演进,来分析其背后涉及到的并发的性能优化思想和实践,最后来看看优化之后的效果。
二、中间件系统的内核机制:双缓冲机制
这个中间件项目整体就不做阐述了,因为涉及核心项目问题。我们仅仅拿其中涉及到的一个内核机制以及对应的场景来给大家做一下说明。
其实这个例子是大量的开源中间件系统、大数据系统中都有涉及到的一个场景,就是:核心数据写磁盘文件。
比如,大数据领域里的hadoop、hbase、elasitcsearch,Java中间件领域里的redis、mq,这些都会涉及到核心数据写磁盘文件的问题。
而很多大型互联网公司自研的中年间系统,同样也会有这个场景。只不过不同的中间件系统,他的作用和目标是不一样的,所以在核心数据写磁盘文件的机制设计上,是有一些区别的。
那么我们公司自研的中间件项目,简单来说,需要实现的一个效果是:开辟两块内存空间,也就是经典的内存双缓冲机制。
然后核心数据进来全部写第一块缓冲区,写满了之后,由一个线程进行那块缓冲区的数据批量刷到磁盘文件的工作,其他线程同时可以继续写另外一块缓冲区。
我们想要实现的就是这样的一个效果。这样的话,一块缓冲区刷磁盘的同时,另外一块缓冲区可以接受其他线程的写入,两不耽误。核心数据写入是不会断的,可以持续不断的写入这个中间件系统中。
我们来看看下面的那张图,也来了解一下这个场景。
如上图,首先是很多线程需要写缓冲区1,然后是缓冲区1写满之后,就会由写满的那个线程把缓冲区1的数据刷入磁盘文件,其他线程继续写缓冲区2。
这样,数据批量刷磁盘和持续写内存缓冲,两个事儿就不会耽误了,这是中间件系统设计中极为常用的一个机制,大家看下面的图。
三、百万并发的技术挑战
先给大家说一下这个中间件系统的背景:这是一个服务某个特殊场景下的中间件系统,整体是集群部署。
然后每个实例部署的都是高配置机器,定位是单机承载并发达到万级甚至十万级,整体集群足以支撑百万级并发,因此对单机的写入性能和吞吐要求极为高。
在超高并发的要求之下,上图中的那个内核机制的设计就显得尤为重要了。弄的不好,就容易导致写入并发性能过差,达不到上述的要求。
此外在这里多提一句,类似的这种机制在很多其他的系统里都有涉及。比如之前一篇文章:《降级机制设计不当,线上系统瞬间崩溃...》,那里面讲的一个系统也有类似机制。
只不过不同的是,那篇文章是用这个机制来做MQ集群整体故障时的容灾降级机制,跟本文的高并发中间件系统还有点不太一样,所以在设计上考虑的一些细节也是不同的。
而且,之前那篇文章的主题是讲这种内存双缓冲机制的一个线上问题:瞬时超高并发下的系统卡死问题。
四、内存数据写入的锁机制以及串行化问题
首先我们先考虑第一个问题,你多个线程会并发写同一块内存缓冲,这个肯定有问题啊!
因为内存共享数据并发写入的时候,必须是要加锁的,否则必然会有并发安全问题,导致内存数据错乱。
所以在这里,我们写了下面的伪代码,先考虑一下线程如何写入内存缓冲。
好了,这行代码弄好之后,对应着下面的这幅图,大家看一下。
看到这里,就遇到了Java并发的第一个性能问题了,你要知道高并发场景下,大量线程会并发写内存的,你要是直接这样加一个锁,必然会导致所有线程都是串行化。
即一个线程加锁,写数据,然后释放锁。接着下一个线程干同样的事情。这种串行化必然导致系统整体的并发性能和吞吐量会大幅度降低的。
五、内存缓冲分片机制+分段枷锁机制
因此在这里必须要对内存双缓冲机制引入分段加锁机制,也就是将内存缓冲切分为多个分片,每个内存缓冲分片就对应一个锁。
这样的话,你完全可以根据自己的系统压测结果,调整内存分片数量,提升锁的数量,进而允许大量线程高并发写入内存。
我们看下面的伪代码,对这块就实现了内存缓冲分片机制:
好!我们再来看看,目前为止的图是什么样子的:
这里因为每个线程仅仅就是加锁,写内存,然后释放锁。
所以,每个线程持有锁的时间是很短很短的,单个内存分片的并发写入经过压测,达到每秒几百甚至上千是没问题的,因此线上系统我们是单机开辟几十个到上百个内存缓冲分片的。
经过压测,这足以支撑每秒数万的并发写入,如果将机器资源使用的极限,每秒十万并发也是可以支持的。
六、缓冲区写满时的双缓冲交换
那么当一块缓冲区写满的时候,是不是就必须要交换两块缓冲区?接着需要有一个线程来将写满的缓冲区数据刷写到磁盘文件中?
此时的伪代码,大家考虑一下,是不是如下所示:
同样,我们通过下面的图来看看这个机制的实现:
七、且慢!刷写磁盘不是会导致锁持有时间过长吗?
且慢,各位同学,如果按照上面的伪代码思路,一定会有一个问题:要是一个线程,他获取了锁,开始写内存数据。
然后,发现内存满了,接着直接在持有锁的过程中,还去执行数据刷磁盘的操作,这样是有问题的。
要知道,数据刷磁盘是很慢的,根据数据的多少,搞不好要几十毫秒,甚至几百毫秒。
这样的话,岂不是一个线程会持有锁长达几十毫秒,甚至几百毫秒?
这当然不行了,后面的线程此时都在等待获取锁然后写缓冲区2,你怎么能一直占有锁呢?
一旦你按照这个思路来写代码,必然导致高并发场景下,一个线程持有锁上百毫秒。刷数据到磁盘的时候,后续上百个工作线程全部卡在等待锁的那个环节,啥都干不了,严重的情况下,甚至又会导致系统整体呈现卡死的状态。
八、内存 + 磁盘并行写机制
所以此时正确的并发优化代码,应该是发现内存缓冲区1满了,然后就交换两个缓冲区。
接着直接就释放锁,释放锁了之后再由这个线程将数据刷入磁盘中,刷磁盘的过程是不会占用锁的,然后后续的线程都可以继续获取锁,快速写入内存,接着释放锁。
大家先看看下面的伪代码的优化:
按照上面的伪代码的优化,此时磁盘的刷写和内存的写入,完全可以并行同时进行。
因为这里核心的要点就在于大幅度降低了锁占用的时间,这是java并发锁优化的一个非常核心的思路。
大家看下面的图,一起来感受一下:
九、为什么必须要用双缓冲机制?
其实看到这里,大家可能或多或少都体会到了一些双缓冲机制的设计思想了,如果只用单块内存缓冲的话,那么从里面读数据刷入磁盘的过程,也需要占用锁,而此时想要获取锁写入内存缓冲的线程是获取不到锁的。
所以假只用单块缓冲,必然导致读内存数据,刷入磁盘的过程,长时间占用锁。进而导致大量线程卡在锁的获取上,无法获取到锁,然后无法将数据写入内存。这就是必须要在这里使用双缓冲机制的核心原因。
十、总结
最后做一下总结,本文从笔者团队自研的百万并发量级中间件系统的内核机制出发,给大家展示了Java并发中加锁的时候:
- 如何利用双缓冲机制
 - 内存缓冲分片机制
 - 分段加锁机制
 - 磁盘 + 内存并行写入机制
 - 高并发场景下大幅度优化多线程对锁的串行化争用问题
 - 长时间占用锁的问题
 
其实在很多开源的优秀中间件系统中,都有很多类似的Java并发优化的机制,主要就是应对高并发的场景下大幅度的提升系统的并发性能以及吞吐量。大家如果感兴趣,也可以去了解阅读一下相关的底层源码。
------------- END -------------
另外推荐儒猿课堂的1元系列课程给您,欢迎加入一起学习~
互联网Java工程师面试突击课(1元专享)
SpringCloudAlibaba零基础入门到项目实战(1元专享)
亿级流量下的电商详情页系统实战项目(1元专享)
Kafka消息中间件内核源码精讲(1元专享)
12个实战案例带你玩转Java并发编程(1元专享)
Elasticsearch零基础入门到精通(1元专享)
基于Java手写分布式中间件系统实战(1元专享)
基于ShardingSphere的分库分表实战课(1元专享)
相关推荐
- Excel技巧:SHEETSNA函数一键提取所有工作表名称批量生产目录
 - 
        
首先介绍一下此函数:SHEETSNAME函数用于获取工作表的名称,有三个可选参数。语法:=SHEETSNAME([参照区域],[结果方向],[工作表范围])(参照区域,可选。给出参照,只返回参照单元格...
 
- Excel HOUR函数:“小时”提取器_excel+hour函数提取器怎么用
 - 
        
一、函数概述HOUR函数是Excel中用于提取时间值小时部分的日期时间函数,返回0(12:00AM)到23(11:00PM)之间的整数。该函数在时间数据分析、考勤统计、日程安排等场景中应用广泛。语...
 
- Filter+Search信息管理不再难|多条件|模糊查找|Excel函数应用
 - 
        
原创版权所有介绍一个信息管理系统,要求可以实现:多条件、模糊查找,手动输入的内容能去空格。先看效果,如下图动画演示这样的一个效果要怎样实现呢?本文所用函数有Filter和Search。先用filter...
 
- FILTER函数介绍及经典用法12:FILTER+切片器的应用
 - 
        
EXCEL函数技巧:FILTER经典用法12。FILTER+切片器制作筛选按钮。FILTER的函数的经典用法12是用FILTER的函数和切片器制作一个筛选按钮。像左边的原始数据,右边想要制作一...
 
- office办公应用网站推荐_office办公软件大全
 - 
        
以下是针对Office办公应用(Word/Excel/PPT等)的免费学习网站推荐,涵盖官方教程、综合平台及垂直领域资源,适合不同学习需求:一、官方权威资源1.微软Office官方培训...
 
- WPS/Excel职场办公最常用的60个函数大全(含卡片),效率翻倍!
 - 
        
办公最常用的60个函数大全:从入门到精通,效率翻倍!在职场中,WPS/Excel几乎是每个人都离不开的工具,而函数则是其灵魂。掌握常用的函数,不仅能大幅提升工作效率,还能让你在数据处理、报表分析、自动...
 
- 收藏|查找神器Xlookup全集|一篇就够|Excel函数|图解教程
 - 
        
原创版权所有全程图解,方便阅读,内容比较多,请先收藏!Xlookup是Vlookup的升级函数,解决了Vlookup的所有缺点,可以完全取代Vlookup,学完本文后你将可以应对所有的查找难题,内容...
 
- 批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数
 - 
        
批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数在电商运营、物流对账等工作中,经常需要统计快递“揽收到签收”的耗时——比如判断某快递公司是否符合“3天内送达”的服务承...
 
- Excel函数公式教程(490个实例详解)
 - 
        
Excel函数公式教程(490个实例详解)管理层的财务人员为什么那么厉害?就是因为他们精通excel技能!财务人员在日常工作中,经常会用到Excel财务函数公式,比如财务报表分析、工资核算、库存管理等...
 
- Excel(WPS表格)Tocol函数应用技巧案例解读,建议收藏备用!
 - 
        
工作中,经常需要从多个单元格区域中提取唯一值,如体育赛事报名信息中提取唯一的参赛者信息等,此时如果复制粘贴然后去重,效率就会很低。如果能合理利用Tocol函数,将会极大地提高工作效率。一、功能及语法结...
 
- Excel中的SCAN函数公式,把计算过程理清,你就会了
 - 
        
Excel新版本里面,除了出现非常好用的xlookup,Filter公式之外,还更新一批自定义函数,可以像写代码一样写公式其中SCAN函数公式,也非常强大,它是一个循环函数,今天来了解这个函数公式的计...
 
- Excel(WPS表格)中多列去重就用Tocol+Unique组合函数,简单高效
 - 
        
在数据的分析和处理中,“去重”一直是绕不开的话题,如果单列去重,可以使用Unique函数完成,如果多列去重,如下图:从数据信息中可以看到,每位参赛者参加了多项运动,如果想知道去重后的参赛者有多少人,该...
 
- Excel(WPS表格)函数Groupby,聚合统计,快速提高效率!
 - 
        
在前期的内容中,我们讲了很多的统计函数,如Sum系列、Average系列、Count系列、Rank系列等等……但如果用一个函数实现类似数据透视表的功能,就必须用Groupby函数,按指定字段进行聚合汇...
 
- Excel新版本,IFS函数公式,太强大了!
 - 
        
我们举一个工作实例,现在需要计算业务员的奖励数据,右边是公司的奖励标准:在新版本的函数公式出来之前,我们需要使用IF函数公式来解决1、IF函数公式IF函数公式由三个参数组成,IF(判断条件,对的时候返...
 
- Excel不用函数公式数据透视表,1秒完成多列项目汇总统计
 - 
        
如何将这里的多组数据进行汇总统计?每组数据当中一列是不同菜品,另一列就是该菜品的销售数量。如何进行汇总统计得到所有的菜品销售数量的求和、技术、平均、最大、最小值等数据?不用函数公式和数据透视表,一秒就...
 
- 一周热门
 
- 最近发表
 - 
- Excel技巧:SHEETSNA函数一键提取所有工作表名称批量生产目录
 - Excel HOUR函数:“小时”提取器_excel+hour函数提取器怎么用
 - Filter+Search信息管理不再难|多条件|模糊查找|Excel函数应用
 - FILTER函数介绍及经典用法12:FILTER+切片器的应用
 - office办公应用网站推荐_office办公软件大全
 - WPS/Excel职场办公最常用的60个函数大全(含卡片),效率翻倍!
 - 收藏|查找神器Xlookup全集|一篇就够|Excel函数|图解教程
 - 批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数
 - Excel函数公式教程(490个实例详解)
 - Excel(WPS表格)Tocol函数应用技巧案例解读,建议收藏备用!
 
 
- 标签列表
 - 
- 外键约束 oracle (36)
 - oracle的row number (32)
 - 唯一索引 oracle (34)
 - oracle in 表变量 (28)
 - oracle导出dmp导出 (28)
 - 多线程的创建方式 (29)
 - 多线程 python (30)
 - java多线程并发处理 (32)
 - 宏程序代码一览表 (35)
 - c++需要学多久 (25)
 - css class选择器用法 (25)
 - css样式引入 (30)
 - css教程文字移动 (33)
 - php简单源码 (36)
 - php个人中心源码 (25)
 - php小说爬取源码 (23)
 - 云电脑app源码 (22)
 - html画折线图 (24)
 - docker好玩的应用 (28)
 - linux有没有pe工具 (34)
 - 可以上传视频的网站源码 (25)
 - 随机函数如何生成小数点数字 (31)
 - 随机函数excel公式总和不变30个数据随机 (33)
 - 所有excel函数公式大全讲解 (22)
 - 有动图演示excel函数公式大全讲解 (32)
 
 
