Java内存模型JMM
文章来自 shichang // Welcome!
主页
|
About Me
|
归档
|
标签
所有的共享资源存储在主内存中,每个线程同时具有自己独立的工作内存。 工作内存中存放了主内存中变量和资源的拷贝,线程不能直接读取主内存中的数据,也不能读取其他线程的工作内存中的数据,线程之间变量值的传递需要通过主内存来进行。 ### 内存交互 虚拟机中定义了以下8中操作来实现主内存与工作内存之间的交互: 作用于主内存: - lock: 将一个变量标志为线程独占的状态 - unlock: 将一个处于锁定状态的变量解锁 - read: 将一个变量的值从主内存中传输到线程的工作内存中 - write : 从store操作得到的变量值放入主内存的变量中 作用于工作内存: - load: 将read得到的变量值放进线程的工作内存的变量副本中 - use: 将工作内存中一个变量的值传递给执行引擎,在虚拟机遇到一个需要使用变量值的字节码指令时会执行此操作 - assign: 将从执行引擎接收到的值赋给工作内存中的变量,在虚拟机遇到一个给变量赋值的字节码指令时会执行此操作 - store: 将工作内存中一个变量的值传递到主内存中,给接下来的write操作使用 这8中操作都是原子操作,一共四组,每一个操作不能单独出现,不能乱序执行 ### volatile volatile关键字有两种语义: 1. 保证变量对其他线程的可见性,普通变量在进行修改之后同步到主内存中,其他线程从主内存中读取时新变量值才会对其他线程可见,使用volatile关键字修饰后线程对变量修改,变量值同步到主内存,并推送到所有其他线程的工作内存中。 2. 禁止指令重排序: 在编译后的代码中插入内存屏障指令使得编译器不能将后续的代码重排序到屏障之前。CPU允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理。在代码段前后没有依赖时,可能会发生指令重排序。 volatile使用规则:运算结果不依赖变量的当前值,volatile不保证原子性 volatile的虚拟机指令实现: - 先read后load操作绑定 - 先assign后store操作绑定 - 如果对变量A的use,assign先于B,那么对A的read,write先于B volatile, synchronized, final都可以实现变量的可见性。 ### 元空间 虚拟机中存在线程共享的方法区用来存储类的信息、常量池、方法数据、方法代码等。HotSpot对方法区的实现是PermGen即永久代,由于类有时是动态加载的,难以预计方法区会需要占用的内存空间大小,所以方法区非常容易出现`OutOfMemoryError`。在JDK1.8之后,Java彻底的将永久代从虚拟机中移出了,其中原来方法区中的静态变量被移动到了堆区中。其余的部分被移出了虚拟机,在虚拟机外利用本地内存构建了一片元空间(Metaspace)以承接这一部分数据。
Pre:
MySQL存储过程和事务
Next:
Java线程池