JMM模型是什么?

查看原文icon-default.png?t=M85Bhttps://mp.weixin.qq.com/s?__biz=MzI3MTA1ODkzNg==&mid=2247488552&idx=1&sn=8faa38027d589f4aa5d250331e00b515&chksm=eac6c6bfddb14fa99044ee02aa87f70ecbb1abaae4bc4698158b1c28a78bffcd8210b891df43&token=325622416&lang=zh_CN#rd

JMM模型是什么?

    Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。需要JVM的实现都需要遵守这样的规范,有了JMM规范的保bujj,并发程序运行在不同的虚拟机上时,所得到的程序结果才是安全可靠可信赖、不同JVM运行结果一致。

百度百科:            

https://baike.baidu.com/item/java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/3399303

个人理解:比如读大学的时候有来自全国各地(不同硬件厂商、操作系统),但是只要是属于这个大学的学生,由学校统一安排(屏蔽差异)好每个人的学号(线程id)、教室(运行)、住宿(存储空间)等。

JMM主要解决什么问题?

55f20aacb66dee5825ae09dadcaab348.png

        由于我们软件是运行于硬件上面的,但是各大厂的硬件有所区别,导致可能在三星主板上和微星上面可能有所不一样,还有在windows、linux等系统上的系统上面所支持内存访问也有所区别,导致可能出现不一样的结果。由于java是跨平台的,基于这些差异,保证了java程序在各种平台下对内存的访问都能保证一致的执行结果,所以引入了JMM来屏蔽掉各种硬件和操作系统的内存访问差异,实现让java程序在各种平台下都通达到一致的内存访问效果。

当然由于JMM也存在共享数据区域,所以就会存在数据的 原子性、可见性、有序性。JMM通过java提供的 volatile解决可见性、通过synchronized和lock来解决有序性,那么原子性通过锁的方向进行实现。

JMM三大特性:原子性、可见性、有序性

    原子性:一个或多个操作,要么全部成功,要么全部失败(不会存在中间状态);

    可见性:指的修改了某个共享变量的值,其他线程可以立即获取到最新值;

    有序性:指程序按照顺序从上到下,从左至右执行;

什么是happens-before 原则?

Happens-before是一个概念,一种现象,或者仅仅是一组规则,它定义了编译器或CPU对指令进行重新排序的基础。Happens-before不是Java语言中的任何关键字或对象,它只是一种规则,以便在多线程环境中,周围指令的重新排序不会导致代码产生不正确的输出。

happens-before 规定如下:

  • 程序顺序规则(Program Order Rule):一个线程内,代码的执行顺序是从上到下(写在前面的先执行);

  • volatile变量规则(Volatile Variable Rule):volatile变量的变化,后续对所读的对象都是可见的。(即一改变立即可见)

  • 管程锁定规则(Monitor Lock Rule):一个unlock操作先行发生于后面对同一个锁的lock操作。(先解再加锁)

  • 线程启动规则(Thread Start Rule):Thread对象start()方法先于其他操作。(先启动再能做其它操作)

  • 线程终止规则(Thread Termination Rule):线程中的所有操作都先于线程的终结。(终结是生命周期最后)

  • 线程中断规则(Thread Interruption Rule):对线程interrupt()方法的先于检测(先被中断才能被检测出来被中断了)

  • 对象终结规则(Finalizer Rule) :一个对象的初始化完成(构造函数结束)先发生它的finalize()方法的开始。(先创建才能finalize)

  • 传递性(Transitivity):如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论。(顺序执行)

在java中从源码到最终执行会经历(源代码->编译器优化重排序->指令级并行重排序->内存系统重排序->最终执行的批评令序列)。jdk5开始,java使用新的JSR-133内存模型,其中就包括Happens-before,从而来辅助JMM中有序性通过通过硬件层面的as-if-serial来标识不让执行结果改变,来保证结果的一致性。

注意:volatile是禁止重排优化的。

参考:

    https://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html

    https://www.geeksforgeeks.org/happens-before-relationship-in-    java/#:~:text=Happens-before%20is%20not%20any%20keyword%20or%20object%20in,result%20in%20a%20code%20that%20produces%20incorrect%20output.

https://dzone.com/articles/happens-before-in-java-or-how-to-write-thread-safe

主内存与工作内存有什么区别?

主内存:主要用于存储的是java实例的对象,所有线程创建的实例对象都存放在这里,当然包括实例对象、成员变量、方法中的本地变量(局部变量)、静态变量、常量、及共享的类信息,往往这里存在多个线程同时访问和操作导致的线程安全问题。

工作内存:主要指的是线程从主内存拷贝使用到的变量副本,仅线本线程使用,其他线程不可见。

个人理解:主内存类似于露天停车场,大家都可以用(共用),工作内存类似于自已私有停车场(专用),当然这个有可能是租的,就是公共里面一些又特别收费的,呵呵~。

JMM的规定、操作及规则

规定

  • 所有的共享变量都存储在主内存中;

  • 每条线程都有自已的工作内存(类似高速缓存);

  • 线程的工作内存保存被该线程使用到的变量的主内存副本拷贝;

  • 线程对变量的所有操作(curd)都必须在工作内存中进行;

  • 不同线程无法直接访问对方工作内存中的变量,线程值传递必须由主内存完成;

操作

  • read 读取:作用于主内存,将共享变量从主内存传送到线程的工作内存中。

  • load 载入:作用于工作内存,把 read 读取的值放到工作内存中的副本变量中。

  • store 存储:作用于工作内存,把工作内存中的变量传送到主内存中。

  • write 写入:作用于主内存,把从工作内存中 store 传送过来的值写到主内存的变量中。

  • use 使用:作用于工作内存,把工作内存的值传递给执行引擎,当虚拟机遇到一个需要使用这个变量的指令时,就会执行这个动作。

  • assign 赋值:作用于工作内存,把执行引擎获取到的值赋值给工作内存中的变量,当虚拟机栈遇到给变量赋值的指令时,就执行此操作。

  • lock锁定:作用于主内存,把变量标记为线程独占状态。

  • unlock解锁:作用于主内存,它将释放独占状态。

规则

  • 不允许一个线程无原因地把数据从工作央存同步到主内存中;

  • 不允许一个线程丢弃最近assign的操作而不同步到主内存中;

  • 不允许一个变量在主内存多过”诞生“,也不允许在工作内存直接使用未初始化(load或assign)的变量;

  • 不允许一个变量在同一时刻有多个线程对其进行lock操作,仅允许一个线程Lock住并重复执行多次,多次lock需要相同次数的unlock操作,变量才会解锁。

  • 一个变量被Lock,会将清空工作内存中的此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。

  • 不允许UnLock,一个没有lock的变量,也不允许unlock一个被其他线程Lock的对象;

  • 一个变量被执行unlock操作之前必须先把该变量同步回主内存中(执行store、write操作)

JMM不同于jvm模型有什么区别?

54e9210a977975e0da2df5b17697c7ad.png

对比名称

JMM

jvm内存

解决问题

原子性、有序性、可见性展开

对象内存开辟及生命周期

划分区别

工作区和公共内存数据区域

方法区、堆、JVM栈、本地方法栈、程序计数器

最后

    根据JMM来了解java其实对于内存的操作有一个严格的标准规则,就类似于我们汽车在路上要遵循交通规则一样来约束我们安全驾驶,特别是这happens-before的使用很层使JMM的有序性得到进一步的保障。当然本人只讲JMM其时还有内存屏障未写到,考虑到篇幅原因后续再完善,有想再深入同学可以先了解一下cpu多级缓存以及下面的一些参考文章。

参考文章:

https://www.cs.umd.edu/~pugh/java/memoryModel/

https://blog.csdn.net/LYQ20010417/article/details/124138635

https://segmentfault.com/a/1190000017395235

https://zhuanlan.zhihu.com/p/372288168

https://blog.csdn.net/GarfieldEr007/article/details/83315848

https://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html

https://lamport.azurewebsites.net/pubs/time-clocks.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值