以下内容摘抄于《深入理解Java虚拟机》第二版中的第十二章
什么是JMM?
JMM(Java Memory Model):Java内存模型,JVM中规范通过JMM来屏蔽掉各种硬件之间和操作系统之间的访问差异,以实现Java程序在各个平台下都能达到一致的内存访问效果(平台无关性)。
JMM的作用?
Java内存模型的主要目的是定义程序中各个变量(这里的变量是指实例字段、静态字段和构成数组对象的元素,但是不包括局部变量和方法参数,因为局部变量和方法参数都是存放在栈中的,线程私有即不会被线程共享,自然就不会存在着竞争的问题)的访问规则。
JMM规定了所有的变量都存储在主内存中。每个线程都有自己的工作内存,线程的工作内存中存放着该线程使用到的变量和主内存副本拷贝,线程对变量的所有操作(读取、赋值操作)都是在线程的工作内存中执行的,而不能直接读写工作内存中的变量。不同线程之间的也无法访问对方的工作内存中的变量,(内存可见性)线程之间的变量值的传递均需要通过主内存来完成。
为什么会线程不安全?
通过以上描述知道,当一个线程需要对一个共享变量进行读写操作的时候,首先需要将主内存中的变量拷贝到自己的工作内存,修改完成后在写回工作内存中。假如有两个线程同时读取主内存中的共享变量到自己的工作内存中进行操作(加入是一个加一操作),那么导致的结果是:在两个线程中都对变量进行了一次+1,但是写到主内存中实际上只是进行了一次+1,这样导致最后得到的结果会比期望值要小。
同步的八种操作
一个变量时如何从主内拷贝到工作内存中的,又是如何从工作内存同步到主内存的?那么JMM中定义了以下8中操作来完成。
1. lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态;
2. unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定;
3. read(读取):作用于主内存的变量,把一个变量从主内存传输到工作内存中,以便随后的load操作使用;
4. load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量的值放入到工作内存的变量副本中;
5. use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎;
6. assign(复制):作用于工作内存的变量,把一个从执行引擎中接收到的值赋值给工作内存的变量;
7. store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传递到主内存中,以便随后的write操作;
8. write(写入):作用于主内存的变量,它把store操作从工作内存中 一个变量的值传递的到主内存的变量中。