简约大气风格网站模板,网上国网推广方案,建网站要花费多少钱,网站建设怎样设置动态背景JAVA内存模型#xff08;JMM#xff09;共享变量#xff1a;如果一个变量在多个线程的工作内存中都存在副本#xff0c;那么这个变量就是这几个线程的共享变量。 上面的工作内存其实是java内存模型抽象出来的概念#xff0c;下面简要介绍一下java内存模型#xff08;JMMJMM共享变量如果一个变量在多个线程的工作内存中都存在副本那么这个变量就是这几个线程的共享变量。 上面的工作内存其实是java内存模型抽象出来的概念下面简要介绍一下java内存模型JMM。 java内存模型java memory model): 描述了java程序中各种变量线程共享变量的访问规则以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。
不同的平台内存模型是不一样的我们可以把内存模型理解为在特定操作协议下对特定的内存或高速缓存进行读写访问的过程抽象。Java 虚拟机规范中试图定义一种 Java 内存模型Java Memory Model简称 JMM来屏蔽掉各种硬件和操作系统的内存访问差异以实现让 Java 程序在各种平台下都能达到一致的内存访问效果不必因为不同平台上的物理机的内存模型的差异对各平台定制化开发程序。 更具体一点说Java 内存模型提出目标在于定义程序中各个变量的访问规则即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。 从上图可以得出结论:
所有的变量都存储在主内存中每个线程都有自己独立的工作内存里面保存该线程使用到的变量的副本主内存该变量的一份拷贝。
JMM关于synchronized的两条规定
线程解锁前必须把共享变量的最新值刷新到主内存中线程加锁时将清空工作内存中共享变量的值从而使用共享变量时需要从主内存中重新读取最新的值。加锁和解锁需要是同一把锁 线程解锁前对共享变量的修改在下次加锁前对其他线程可见。 JVM主内存与工作内存描述
JVM将内存为主内存和工作内存两个部分。
主内存: 主要包括本地方法区和 堆
Java 内存模型规定了所有变量都存储在主内存(Main Memory)中此处的主内存与介绍物理硬件的主内存名字一样两者可以互相类比但此处仅是虚拟机内存的一部分。
工作内存: 每个线程都有一个工作内存工作内存中主要包括两个部分一个是属于该线程私有的栈和 对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。
每个线程都有自己的工作内存(Working Memory又称本地内存.)线程的工作内存中保存了该线程使用到的变量该变量是主内存中的共享变量的副本拷贝。(工作内存是 JMM 的一个抽象概念并不真实存在。它涵盖了缓存写缓冲区寄存器以及其他的硬件和编译器优化。) 线程执行的时候将首先从主内存读值再load到工作内存中的副本中然后传给处理器执行执行完毕后再给工作内存中的副本赋值随后工作内存再把值传回给主存主存中的值才更新。 在这个过程中如果出现多个线程同时在处理这些值岂不是会出现并发问题 1、所有的变量都存储在主内存中(虚拟机内存的一部分)对于所有线程都是共享的 2、每个线程都有自己的工作内存工作内存中保存的是主存中某些变量的值的副本拷贝线程对变量的所有操作都必须在工作内存中进行不能直接读写主内存中的变量。 3、线程之间无法直接访问对方的工作内存中的变量值的线程间变量的传递均需要通过主内存来完成。 这种划分与Java运行时内存区域中堆、栈、元空间等的划分是不同层次的划分两者基本没有关系。硬要联系的话大致上主内存对应Java堆中对象的实例数据部分、工作内存对应栈的部分区域从更低层次上说主内存对应物理硬件内存、工作内存对应寄存器和高速缓存。 JVM内存间交互规则
关于主内存与工作内存之间的具体交互协议即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步回主内存之类的实现细节Java 内存模型中定义了下面 8 种操作来完成。
Lock(锁定)作用于主内存中的变量把一个变量标识为被一个线程独占的状态。Unlock(解锁)作用于主内存中的变量 将一个变量从锁定状态(Lock)释放出来释放后的变量才可以被其他线程锁定(Lock)Read(读取)作用于主内存中的变量将一个变量的值从主内存传输到工作内存中以便随后的load操作使用Load(加载)作用于工作内存中的变量把read操作从主内存中得到的变量的值放入工作内存的变量副本中。Use(使用)作用于工作内存中的变量把工作内存中一个变量的值传递给执行引擎。每当虚拟机遇到一个需要使用到变量的值的字节码指令时就会执行这个操作。Assign(赋值)作用于工作内存中的变量把一个从执行引擎接收到的值赋值给工作内存中的变量。每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。Store(存储)作用于工作内存中的变量把工作内存中的一个变量的值传送到主内存中以便随后 write 操作使用。Write(写入)作用于主内存中的变量把store操作从工作内存中得到的变量的值放入主内存的变量中。
需知:
在将变量从主内存读取到工作内存中必须顺序执行read(读取)、load(加载)要将变量从工作内存同步回主内存中必须顺序执行store(存储)、write(写入)。
这8种操作必须遵循以下规则 不允许read(读取)和load(加载)、store(存储)和write(写入)操作之一单独出现。即不允许一个变量从主内存被读取了但是工作内存不接受或者从工作内存回写了但是主内存不接受。 不允许一个线程无原因地没有发生过任何assign操作把数据从工作内存同步会主内存中 不允许一个线程丢弃它最近的一个assign(赋值)操作即变量在工作内存被更改后必须同步改更改回主内存。即执行store(存储),write(写入)操作 工作内存中的变量在没有执行过assign(赋值)操作时不允许无意义的同步回主内存。 即执行store(存储),write(写入)操作 在执行use(使用)前必须已执行load(加载在执行store(存储)前必须已执行assign(赋值。 一个变量在同一时刻只允许一个线程对其执行lock操作一个线程可以对同一个变量重复执行多次lock多次执行lock后只有执行相同次数的unlock操作变量才会被解锁。lock和unlock必须成对出现。 一个线程在lock一个变量的时候将会清空工作内存中的此变量的值执行引擎在use(使用)前必须重新read(读取)和load(加载)初始化变量的值。 在执行unlock之前必须首先执行了store(存储)和write(写入)操作 对一个变量执行unlock操作之前必须先把此变量同步到主内存中执行store和write操作 线程不允许unlock其他线程的lock操作。并且unlock操作必须是在本线程的lock操作之后。 如果一个变量事先没有被lock操作锁定则不允许对它执行unlock操作也不允许去unlock一个被其他线程锁定的变量。
从上面可以看出把变量从主内存复制到工作内存需要顺序执行read、load从工作内存同步回主内存则需要顺序执行store、write。总结
read、load、use必须成对顺序出现但不要求连续出现。assign、store、write同之变量诞生和初始化变量只能从主内存“诞生”且须先初始化后才能使用即在use/store前须先load/assignlock一个变量后会清空工作内存中该变量的值使用前须先初始化unlock前须将变量同步回主内存一个变量同一时刻只能被一线程locklock几次就须unlock几次未被lock的变量不允许被执行unlock一个线程不能去unlock其他线程lock的变量。
JVM先行发生原则 Java内存模型具备一些先天的“有序性”即不需要通过任何同步手段volatile、synchronized等就能够得到保证的有序性这个通常也称为happens-before原则。 知识来源
【23版面试突击】你知道主内存和工作内存的关系_哔哩哔哩_bilibili
【Java多线程】内存模型JMM—主内存与工作内存分析_主内存和工作内存_Archie_java的博客-CSDN博客