GitHub 4.1k Star 的Java工程师成神之路 ,不来了解一下吗?
GitHub 4.1k Star 的Java工程师成神之路 ,真的不来了解一下吗?
GitHub 4.1k Star 的Java工程师成神之路 ,真的确定不来了解一下吗?
最近,面试过很多Java中高级开发,问过很多次关于Java内存模型的知识,问完之后,很多人上来就开始回答:
Java内存模型由几部分组成,堆、本地方法栈、虚拟机栈、方法区...
每一次我不想打断他们的话,虽然我知道这又是一个误会了我的问题的朋友。
其实,我想问的Java内存模型,是和并发编程有关的。而候选人给我回答的那叫JVM内存结构,完全是两回事。
很多时候,在我没有打断他们的情况下,一部分人慢慢的讲到了GC相关的知识。这种情况下,我只能硬着头皮继续问一些和JVM有关的知识。
但是,我的本意其实是想看一下他对Java并发有多少了解啊。
经常,我都在继续追问了一些他们回答的"Java内存模型"相关的知识后,友善的提醒一句,其实我想问的Java内存模型并不是他回答的这个...
有的时候,我会进一步提醒一句:是和并发编程有关的,是和主内存以及线程工作内存有关的。。。
那么,本文就来简单说一说,关于Java内存模型,到底应该如何回答这个面试题。
为什么会误解
首先,我们先来分析一下问什么很多人,甚至是大多数人会答非所问呢?
我觉得主要有几个原因:
1、Java内存模型,这个词听着太像是关于内存分布的知识了。听上去和并发编程没有半毛钱关系。
2、网上很多资料都是错的。不信你去网上搜索一下"Java内存模型",你会发现,很多人打着内存模型的标题,介绍了JVM内存结构的知识。
这里提一句,我尝试着Google搜索了一下搜索"Java内存模型",首页展示结果如下:
首页排名靠前的5篇文章中,有1篇是错的,介绍了JVM内存结构。
PS:值得庆幸的的是,首页前5篇文章中,有两篇是我写的,至少我的这两篇我敢确定是不具备任何误导性的!!
3、还存在一种情况,虽然不多见,但是也有。那就是很多面试官自己也以为内存模型就是要介绍堆、栈、方法区这些知识。就导致有时候面试者不知道自己到底应该如何回答。
那么,到底什么是Java内存模型?关于这道面试题应该如何回答呢?
什么是内存模型
我曾经在《 再有人问你Java内存模型是什么,就把这篇文章发给他 》中详细的介绍过Java内存模型的来龙去脉,这里再重新回顾一下。
Java内存模型是根据英文Java Memory Model(JMM)翻译过来的。其实JMM并不像JVM内存结构一样是真实存在的。他只是一个抽象的概念。
Java内存模型的相关知识在 JSR-133: Java Memory Model and Thread Specification 中描述的。JMM是和多线程相关的,他描述了一组规则或规范,这个规范定义了一个线程对共享变量的写入时对另一个线程是可见的。
Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能得到一致效果的机制及规范。目的是解决由于多线程通过共享内存进行通信时,存在的原子性、可见性(缓存一致性)以及有序性问题。
那么,我们这里就先来说说什么是所谓的内存模型规范、这里提到的原子性、可见性以及有序性又是什么东西?
原子性
线程是CPU调度的基本单位。CPU有时间片的概念,会根据不同的调度算法进行线程调度。所以在多线程场景下,就会发生原子性问题。因为线程在执行一个读改写操作时,在执行完读改之后,时间片耗完,就会被要求放弃CPU,并等待重新调度。这种情况下,读改写就不是一个原子操作。即存在原子性问题。
缓存一致性
在多核CPU,多线程的场景中,每个核都至少有一个L1 缓存。多个线程访问进程中的某个共享内存,且这多个线程分别在不同的核心上执行,则每个核心都会在各自的caehe中保留一份共享内存的缓冲。由于多核是可以并行的,可能会出现多个线程同时写各自的缓存的情况,而各自的cache之间的数据就有可能不同。