Java内存模型JMM

定义

java内存模型(即 java Memory Model,简称JMM),不存在的东西,是一个概念,约定

主要分成两部分来看,一部分叫做主内存,另一部分叫做工作内存。

  • java当中的共享变量;都放在主内存当中,如类的成员变量(实例变量),还有静态的成员变量(类变量),都是存储在主内存中的。每一个线程都可以访问主内存;
  • 每一个线程都有其自己的工作内存,当线程要执行代码的时候,就必须在工作内存中完成。比如线程操作共享变量,它是不能直接在主内存中操作共享变量的,只能够将共享变量先复制一份,放到线程自己的工作内存当中,线程在其工作内存对该复制过来的共享变量处理完后,再将结果同步回主内存中去。

主内存是 所有线程都共享的,都能访问的。所有的共享变量都存储于主内存;共享变量主要包括类当中的成员变量,以及一些静态变量等。局部变量是不会出现在主内存当中的,因为局部变量只能线程自己使用;
工作内存每一个线程都有自己的工作内存,工作内存只存储 该线程对共享变量的副本。线程对变量的所有读写操作都必须在工作内存中完成,而不能直接读写主内存中的变量,不同线程之间也不能直接访问 对方工作内存中的 变量;线程对共享变量的操作都是对其副本进行操作,操作完成之后再同步回主内存当中去;

JMM的同步约定:

  • 线程解锁前,必须把共享变量立刻刷回主存
  • 线程加锁前,必须读取主存中的最新值到工作内存中
  • 加锁和解锁是同一把锁

作用

主要目的就是在多线程对共享变量进行读写时,来保证共享变量的可见性、有序性、原子性;在编程当中是通过两个关键字 synchronized 和 volatile 来保证共享变量的三个特性的。

主内存与工作内存如何交互

一个变量如何从主内存拷贝到工作内存、如何从工作内存同步回主内存的呢?

Java内存模型中定义了上图中的 8 种操作(橙色箭头)来完成,虚拟机实现时必须保证每一种操作都是原子的、不可再分的。

举个例子:假设现在线程1想要来访问主内存当中的共享变量 x ,即当前主内存中的共享变量x的取值为 boolean x = true;

  1. 线程1首先会做一个原子操作叫做Read,读取主内存当中的共享变量x的取值,即 boolean x = true;
  2. 接下来就是 Load 操作,把在主内存中读取到的共享变量加载到了工作内存当中(副本);
  3. 接着执行 Use 操作,如果线程1需要对共享变量x进行操作,即会取到从主内存中加载过来的共享变量x的取值去进行一些操作;
  4. 操作之后会有一个新的结果返回,假设令这个共享变量的取值变为false,完成 Assign 操作,即给共享变量x赋新值;
  5. 操作完成之后;就需要同步回主内存,首先会完成一个 Store 的原子操作,来保存这个处理结果;
  6. 接着执行Write操作,即在工作内存中,Assign 赋值给共享变量的值同步到主内存当中,主内存中共享变量取值x由true更改为false。
  7. 另外还有两个与锁相关的操作,Lock与unlock,比如说加了synchronized,才会产生有lock与unlock操作;如果对共享变量的操作没有加锁,那么也就不会有lock与unlock操作。

注意:如果对共享变量执行 lock 操作,该线程就会去主内存中获取到共享变量的最新值,刷新工作内存中的旧值,保证可见性;(加锁说明要对这个共享变量进行写操作了,先刷新旧值,再操作新值)
对共享变量执行 unlock 操作,必须先把此变量同步回主内存中,再执行 unlock;(因为对共享变量释放锁,接下来其他线程就能访问到这个共享变量,就必须使这个共享变量呈现的是最新值)这两点就是 synchronized为什么能保证“可见性”的原因。

规则:

  1. 不允许read、load、store、write操作之一单独出现,也就是read操作后必须load,store操作后必须write。
  2. 不允许线程丢弃他最近的assign操作,即工作内存中的变量数据改变了之后,必须告知主存。
  3. 不允许线程将没有assign的数据从工作内存同步到主内存。
  4. 一个新的变量必须在主内存中诞生,不允许工作内存直接使用一个未被初始化的变量。就是对变量实施use、store操作之前,必须经过load和assign操作。
  5. 一个变量同一时间只能有一个线程对其进行lock操作。多次lock之后,必须执行相同次数unlock才可以解锁。
  6. 如果对一个变量进行lock操作,会清空所有工作内存中此变量的值。在执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值。
  7. 如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量。
  8. 一个线程对一个变量进行unlock操作之前,必须先把此变量同步回主内存。

总结

主内存 与 工作内存 之间的 数据交互过程(即主内存与工作内存的交互是通过这8个原子操作来保证数据的正确性的):
lock → read → load → use → assign → store → write → unlock

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值