前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JMM模型是什么?

JMM模型是什么?

作者头像
逍遥壮士
发布2022-12-01 15:43:31
4030
发布2022-12-01 15:43:31
举报
文章被收录于专栏:技术趋势技术趋势

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主要解决什么问题?

由于我们软件是运行于硬件上面的,但是各大厂的硬件有所区别,导致可能在三星主板上和微星上面可能有所不一样,还有在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模型有什么区别?

对比名称

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术趋势 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档