作者:进击的码农
链接:https://www.zhihu.com/question/325469611/answer/694336275
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
JVM内存模型的定义
八种原子操作
八种原子操作下的规则
通过以上来定义了JVM的内存模型,也就是我们要遵守的协议
八种原子操作分别为
1.lock 锁定 : 把主内存中的一个变量标志为一个线程独享的状态
2.unlock 解锁 : 把主内存中的一个变量释放出来
3.read 读:将主内存中的变量读到工作内存中
4.load 加载:将工作内存中的变量加载到副本中
5.use 使用:当执行引擎需要使用到一个变量时,将工作内存中的变量的值传递给执行引擎
6.assign 赋值:将执行引擎收的的值赋值给工作内存中的变量
7.store 存储:将工作内存中的变量的值传到主内存中
8.write 写入:将store得到值放到主内存的变量中
八种原子操作下的八种操作规则
1.read和load,store和write必须同时出现,并且按照顺序执行
2.不允许线程丢弃最后一个assign操作,在进行assign操作后,必须进行store和write
3.如果一个线程的工作内存中的一个变量没有发生assign操作,则不能够发生store和write
4.在工作内存中,如果对一个变量使用use或者store操作,则必须先执行assign和load操作
5.一个主内存中的变量在同一时刻只能被一个线程进行lock操作,但是这个线程可以进行多次lock操作,并且执行相应次数的unlock操作后,变量才会被解锁.
6.如果对一个量进行lock操作,将会清空此变量在其他线程工作内存中的值,这些线程在使用之前必须进行load或assign操作
7.一个线程如果没有对一个变量进行lock操作,则这个线程也不能对这个变量进行unlock操作
8.一个线程在进行unlock操作之前,必须先执行store和write操作
先后顺序就是由这八种操作规则,或者说JVM内存模型的协议规定的.是JVM虚拟中内存模型的开发规范.
JVM内存模型长什么样?
运行时内存中的线程共享区域和线程私有区域共同构成了JVM内存模型.
说明 : 这是JVM经典的内存模型.但是,在OpenJDk中,是没有本地方法栈的,本地和JVM共同使用Java方法栈.
方法区中是JDK1.7之前的方法区,1.8之后将常量池移出方法区.
为什么会有JVM内存模型?
为了实现跨平台性.
Java语言的跨平台性的基础,不仅包括Java的解释执行和JIT(即时编译),而且还包括了内存模型的统一.
为什么要实现跨平台?跨平台是面向谁的?
Java是在什么背景下出现的?
CPU厂商众多,主机上产厂商众多,一般情况下,生产 主机的厂商还会自己开发操作系统.
造成的问题?
CPU架构不同,导致指令集不同,操作系统众多,封装的汇编不同.
对编程造成的影响?
如果要更换服务器,或者服务器有多种型号的操作系统主机,则需要根据不同的操作系统制造不同的编译器.是的,不能编译一次,到处运行.并且在这种背景下,众多的CPU和主机厂商,可以说是很费心费力.
主机的物理内存模型.为什么会出现物理主机的内存模型?
CPU的进化史
单核CPU.在这种情况下,内存的IO读写速度和CPU的执行速度相差太大,限制CPU性能的最大问题就是IO读写速度.为了解决这个问题,出现了高速缓存,CPU不再直接和内存交换数据,而是通过高速缓存.
此时IO读写问题已经解决,此时限制CPU的性能的问题是什么呢?
CPU中的运算单元没有得到充分的利用,比如说,一个CPU内的运算单元可以同时进行一万个1+1=2的运算,但是由于CPU是单线程的,如果同时有10000个1+1=2的运算,那么需要进行串行操作.导致了其他的运算单元都没用到.处理问题的方案两个,超线程技术,将一个物理CPU模拟为两个,可以同时执行两个线程.CPU乱序执行,比如一段代码需要从头到尾进行串行操作,那么也就是一个一个指令的去执行,还是串行,资源还是没有得到充分的利用.把这一段命令打乱,在不影响返回结果的情况下,一起执行.其实,乱序执行只是对于外界的一种表现.从CPU内部的角度来说,更适合叫并行执行.
当然,为了提高速度,还有多核CPU的出现.同样的,出现了多线程.那么此时又出现了新的问题.如果两个及以上的线程同时操作内存中的一个变量,且两个线程把这个值都改变了.那么在写入高速缓存时,以谁的值为准呢?在写入内存时,以谁的值为准呢?缓存一致性问题.
上面说到背景,有很多的主机厂商.那么在处理这个问题时就有了不同的解决方案.在不同的主机操作系统中有自己的缓存一致性协议.给编程带来了什么影响?
程序员在进行多线程开发时,要针对不同缓存一致性协议进行开发,针对不同的内存模型进行开发,意思也就是说在进行多线程编程时,不同主机上的代码是不一样的.移值性很差.
JVM是如何解决这个问题的?
屏蔽各种主机的缓存一致性协议,转化为JVM内存模型.在程序员编程时,只要针对JVM的内存模型来编程就可以了.
所以,跨平台是针对于程序员的.
所以在这个背景下,出现了JVM内存模型,表现就是,运行时数据区中的共享内(主内存)存部分和线程私享部分(工作内存).JVM的八种原子操作以及八种操作规则.