• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

Java内存模型

互联网 diligentman 2周前 (01-11) 9次浏览

硬件效率一致性

计算机处理器处理性能跟其他设备之间存在好几个数量级的差别,导致处理执行完成了但是其他硬件设备还需要等待,因此出现了高速缓存这个技术来缓解几个数量级差距。有了缓存与主内存,这中间就会引入数据一致性的问题,这里就需要数据一致性协议来保证

Java内存模型

Java的内存模型如下图,主要存在以下特点:

  • 每个线程都有自己的一份内存变量,里面的内容是从主内存复制的供该线程使用的变量,每个线程修改某个变量的值都是从修改自己的内部工作线程变量开始,不会直接修改主内存的变量值
  • 不同线程之间的通讯需要通过主内存来完成,工作线程变量的值修改,其他线程是无法知道的

Java内存模型

 

  1. 在Java内存模型中,跟硬件与其他内存设备之间的关系是类似的。线程就好比处理器,多线程就好比多核处理器,工作内存好比高速缓存,数据一致性就好比save和load操作,主内存就好比多个数据源共享的内存。主内存变量为静态变量或者全局变量,局部变量不算。
  2. 主内存与线程的工作内存之间的如何实现数据同步,Java内存模型定义了8种交互协议来完成:
  • lock:作用于主内存的变量,把该变量标识为一个线程独占
  • unlock:作用于主内存变量,将该变量释放锁定,释放后可以被其他任何线程竞争获取锁
  • read:作用于主内存变量,是指的将主内存变量传输到线程的工作内存当中,以便于后面的load操作
  • load:作用于工作内存变量,将从主内存read过来的变量载入到工作内存的变量副本当中
  • use:作用于工作内存变量,把工作内存变量的值传给执行引擎,当遇到了一个需要使用工作内存变量值的字节码指令时,虚拟机就会执行use操作
  • assign:作用于工作内存变量,把从执行引擎获取到的值赋给工作内存变量,虚拟机遇到了一个需要给工作内存变量赋值的指令时,就会执行assign操作
  • store:作用于工作内存变量,将工作内存变量传输到主内存变量当中,以便于后面的write操作
  • write:作用于主内存变量,将store操作从工作内存变量获取的值写入到主内存种

Java内存交互原则

Java内存模型规定了指令的顺序,例如变量从主内存到工作内存,必须先后经历read和load,从工作内存再回主内存,必须先后经历store和write操作,这其中的顺序不能颠倒,但是他们执行期间可以任意插入其他指令,所以上述指令操作要求是顺序执行的,但不要求连续执行。例如主内存种两个变量a和b,分别要进行use和assign操作,之前要执行read和load以及store和write,他们的执行顺序可以是read a, store b, write b, load a。

Java内存模型还要求以下原则需要满足:

  • 不允许read和load,store和write两对只出现一个指令,即不允许只有read没有load,或者只有write没有store等。
  • 不允许一个线程修改了变量值,不进行assign操作指令,改变了工作内存中的值,则必须同步回主内存
  • 不允许一个线程没有发生assign操作的情况下把数据从工作内存同步回住内存
  • 一个新变量只能在主内存里面“诞生”,不允许工作内存中直接使用一个未被初始化(load或者assign)的变量,就是说一个变量在进行use和store操作之前,必须先执行过assign和load操作
  • 一个变量在同一个时刻只能有一个线程对其进行加锁(lock)操作,一个线程可以多次lock同一个变量,如果执行了多次lock,那么必须要执行相同次数的释放锁(unlock)操作才能解锁
  • 如果一个变量执行lock操作,会清空所有线程工作内存中的变量值,后续对该变量值得的读取必须从主内存中。无论是普通变量还是volatile变量,都是这样操作的。volatile变量跟普通变量的区别在于volatile变量可以将修改后的值立即同步到主内存中,每次使用之前都从主内存刷新变量,但是普通变量无法做到这样
  • 一个变量如果事先被lock操作锁定,那么久不允许对它执行unlock操作,也不允许它去unlock一个被其他线程锁定的变量
  • 对一个变量进行unlock操作之前,必须要先把变量同步回主内存中(执行store、write操作)

本文参考了《深入理解Java虚拟机》,加入了个人理解并优化了中间可能存在歧义的地方

 

 

{{o.name}}


{{m.name}}


喜欢 (0)