# 《并发设计模式》第02章-不可变模式-原来问题出在这里!

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★☆☆☆
  • 本章重点:掌握多个线程同时读写同一共享变量存在共享问题的根本原因,重点掌握CPU内存模式和Java内存模型的核心原理,缓存一致性问题及其产生的原因,并能够根据CPU内存模型和Java内存模型编写线程安全的代码。

大家好,我是冰河~~

“原来如此啊,真没想到统计个调用商品详情接口次数的功能背后还会牵扯到这么多知识点,这些知识之前确实没听说过,看来确实有很多我之前不知道的东西呀,以后跟着老大好好学,争取跟他一样厉害”,小菜默默的在心里嘀咕着。

# 一、情景再现

小菜凭借着之前在学校的传奇经历顺利进入一家头部互联网公司实习,几天后,被分配到一个统计线上调用商品详情接口的任务,本以为很简单的功能,小菜也三下五除二的完成了开发任务,但是在测试时,却被告知小菜统计出来的结果和实际结果差距太大。经过一天的排查和定位,小菜最终也没有找出问题出在哪里。

# 二、寻求帮助

第二天,小菜早早来到公司,还在思考着昨天为什么自己写的代码明明看起来没问题,却跟实际统计结果差距这么大。

正当小菜还在纠结时,他突然听到:“小菜,怎么样了,知道昨天为什么会出现问题了吗?”。

小菜转过头一看,原来是自己的直属领导老王到公司了,“没有呀,我昨天下班后也在想这个问题,但是还是没找到原因”。

此时,小菜起身来到老王的工位旁边,“老大,昨天我搞到很晚也没发现啥问题,你可以给我讲讲哪里出了问题吗?”。

“可以”,老王一边说着,一边从电脑包里拿出自己的电脑。“其实,要搞清楚为啥昨天你写的代码会出问题,这就涉及到内存模型了,说到内存模型,就要从CPU内存模型和Java内存模型两个方面进行讲述了”。

“这样吧,小菜拿上笔和本,现在会议室没人使用,我单独给你讲讲”。

“好的”,小菜边说,边回到工位拿笔和本子,老王则拿起了自己的电脑,二人一起到会议室走去。

# 三、CPU内存模型

“以前了解过CPU内存模型吗?”。

“在学校听老师讲过,不过讲的不够深入和具体,我也了解的不多,我确实也想不出来这跟昨天实现的功能有啥关系”。

“没关系,我今天给你讲一下”,老王边说,边打开了电脑和投影仪。

“你昨天写的代码出问题,本质上与内存模型有关,说到内存模型呢,又会涉及到CPU内存模型和Java内存模型,我们先来讲讲CPU内存模型吧”,老王将自己的电脑投到投影仪上。

“好的”,小菜边听边在本子上记。

老王接着说:“Java程序一般都是运行在JVM上,JVM本身有自己的内存模型,Java的内存模型其实与CPU的内存模型有很多相似之处。如果是CPU内存模型呢,计算机执行程序时,每条执行指令都是在CPU中执行的,并且在CPU执行指令的过程中就会涉及到数据的读写操作,CPU并不会直接从计算机的磁盘上读数据,而是从计算机的主存,也就是我们常说的内存中读取数据,并且CPU也会将处理的结果数据写回主存”。

老王一边说,一边在脑电上画出了这样一张图,如图2-1所示。


“你在大学里应该学到过,其实CPU的执行速度是非常快的,会比内存的读写速度快的多”,老王画完图说道。

“是的,这个我了解过”,小菜回应道。

“CPU的执行速度和内存的读写速度存在巨大的速度差,这样就会存在一个问题,由于CPU在处理任务时,需要从内存中读取数据,内存的读写速度远远不及CPU的执行速度,这样就会导致CPU的执行速度大大下降”。

“为了解决这个问题,CPU的架构师们在CPU内部设计了一个高速缓冲区,用来平缓CPU执行速度与内存读写速度之间的差距。在执行时,会将CPU执行任务要读取的数据从内存读取到CPU的告诉缓冲区,然后CPU再从高速缓冲区读取数据后执行任务。当CPU执行完任务,也是先将结果数据写回到高速缓冲区,随后再将高速缓冲区的数据刷新到内存,这样CPU的执行效率就大大提升了,我们再来画一张图”。

说完,老王又画了一张图,如图2-2所示。

# 查看全文

加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码