JMM到底如何理解?JMM与MESI到底有没有关系?

今天给大家分享一篇对于理解Java的多线程,特别重要的一个知识点:JMM。在JVM中增加线程机制,首当其冲就是要实现JMM,即Java内存模型。JMM也是大家真正理解Java多线程的基础。

但是大家对于JMM,可以说大多数小伙伴对其的理解是错误的。这篇文章我会从这几个方面讲JMM,让大家获得对JMM正确的、深刻的认识:

1、市面上大家看到的资料是怎么介绍JMM的

2、我会结合一个Linux多线程程序给大家分析,JMM与MESI没有半毛钱关系

3、那为什么要有JMM?不要行不行?

4、Java代码加或不加volatile对于可见性的影响如何理解?

正确认识JMM

有些小伙伴可能第一次听说JMM,大概介绍下:JMM即Java内存模型,不是JVM内存模型。Java的多线程机制是基于JMM实现的。如果你第一次听到这玩意是通过我这篇文章,那恭喜你,你还没有中毒。如果你还想进一步了解,接着往后看。

MESI即CPU的缓存一致性协议。现在取而代之的是MOESI。不同架构的CPU还有可能用其他的协议。理解本篇文章,了解到这个程度就够了,不展开讲。感兴趣的小伙伴可以自行面向百度学习。

你现在百度搜JMM,展示的文章基本都是这个套路:CPU缓存架构、计算机的内存模型、MESI、volatile实时触发数据一致性......不知道这套思路的始祖是谁,把一个简单的JMM讲得复杂得不行,正常人根本就看不懂,甚至被劝退。关键是错的,还能自圆其说地把这些名词串起来讲得像是真的一样。有多少小伙伴有同感的,留言区举个爪。

那如何正确理解JMM呢?一、不要把它与什么CPU、OS内存模型扯上关系。这些区域的数据一致性与JMM无关 。可以想象有一堵墙,墙的一边是OS及硬件,另一边是JVM。JMM只与JVM有关,手没那么长,伸不到墙那边去;二、JMM你可以直接把它理解成工作内存+主内存;三、加或不加volatile跟触发MESI没有半毛钱关系,只是让JVM知道我要不要回写,伪代码如下

假如(该变量被volatile修饰) {
  触发回写,让更改的数据写回主内存。
  其他线程获取到修改的数据存在一个写内存时长的延时
} else {
  不触发回写
}

因为JMM是JVM自己抽象实现的,如果发生了写操作,正常情况工作内存与主内存的数据是不一致的。如果想告诉JVM我需要它一致,就得提供一套机制,这个机制就是volatile的一部分功能。

有两个名词解释一下:主内存,即共享内存,等同于JVM内存模型中的方法区+堆区。工作内存,即私有内存,等同于JVM内存模型中的虚拟机栈。

有些小伙伴可能就要说了:这些都是子牙老师你的个人认识,我们怎么知道是你的正确还是网上的那套呢?是的,没毛病(疯狂记仇)。熟悉我的小伙伴都知道,我要开始上证据了。名声稳不稳得住,就看证据给不给力了。

这个怎么解释

咱们来反证:如果CPU间的缓存一致、CPU缓存与内存间的数据一致需要通过volatile来触发,那操作系统线程间的数据可见性怎么触发?我们会写代码手动触发吗?上一段程序让大家感受下。

代码中没有任何触发机制,大家猜下:线程一sleep前后输出的结果是否都是10?

答案是这次修改是线程可见的。为什么OS的线程天生具备线程可见性,而JMM不具备呢?这个解释起来就比较麻烦了,我会专门出一期内容讲解这个内容。

题外话

总是听到小伙伴说:多线程好难学、多线程学不会、多线程没概念......为什么会这样呢?我觉得可能是这样:大多数小伙伴接触线程都是从高级语言开始的,比如Java。而高级语言的线程是基于操作系统的线程机制实现的,而小伙伴们没有学过操作系统应用层的学习机制,更不了解操作系统内核级的线程机制,所以学完多线程有一种似会非会的感觉。跟别人交流或者面试的时候,滥用应用态切内核态、线程调度等名词。写多线程程序更是惨不忍睹。

我的手写JVM小班新增的内容就是以我所理解的方式让大家精通多线程。学起来会有一点难度,所以如果你没有决心想成为一个技术大牛,建议有这个决心的时候再来,我随时都在。当然啦,底层的学习会比较枯燥,那我是怎么解决这个问题的呢?手写。沉浸在设计者的角度去思考去实现,随着对知识点本身的一点点领悟,代码的一点点成型,那种成就感是CRUD无法比拟的。给大家看下二期新增的知识大纲。

重点来咯!子牙老师亲授,全网唯一的手写JVM小班二期开始招生啦!现在报名享早鸟价。这套课程学下来,如果你真的吸收了,马上领先身边人好几个Level。继续沉淀,多写点作品,简历更加充实,底层实力更加强劲。回过头来学应用层,理解起来特别快,而且理解得比不懂底层的要更加深刻。更重要的是,跟着我学习不会踩坑,能学到实打实的硬核内容。大家看我的视频、我的文章,应该都能感受到,我崇尚的就是硬核。

相关推荐
代码小鑫9 分钟前
A15基于Spring Boot的宠物爱心组织管理系统的设计与实现
java·开发语言·spring boot·后端·毕业设计·宠物
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ15 分钟前
mapper.xml 使用大于号、小于号示例
xml·java·数据库
一直学习永不止步24 分钟前
LeetCode题练习与总结:迷你语法分析器--385
java·数据结构·算法·leetcode·字符串··深度优先搜索
Tech Synapse1 小时前
Java将Boolean转为Json对象的方法
java·开发语言·json
小冉在学习1 小时前
day55 图论章节刷题Part07([53.寻宝]prim算法、kruskal算法)
java·算法·图论
伴野星辰1 小时前
网站视频过大,加载缓慢解决方法【分段加载视频】
java·服务器·音视频
让生命变得有价值1 小时前
k8s 启用 ValidatingAdmissionPolicy 特性
java·容器·kubernetes·kubelet
morning_judger1 小时前
【设计模式系列】享元模式(十五)
java·设计模式·享元模式
I_Am_Me_1 小时前
【JavaEE进阶】HTML
java·java-ee·html
咘噜biu2 小时前
PDF模板制作与填充(Java)
java·pdf·pdf模板