Java内存模型(JMM)
Java内存模型展示的就是每个线程拥有一块私有的本地内存,存储读或写的共享变量的副本。
Java内存模型规定了一个线程如何和何时能够看到由其他线程修改的共享变量的值,以及在必须的时候,如何同步地访问共享变量。
模型基本就是这样的,主内存中存储着共享变量,然后各自的本地内存中存储着共享变量的副本。
多线程环境下,有时候我们写的代码所得到的结果并不是我们想要的,比如说主内存中有一个整型变量i初始值为0,然后呢现在A和B两个线程对i进行加一操作,A和B分别从主内存中取得1后到本地内存,然后进行+1操作,两个都变为了2,然后需要把本地内存中的变量同步到主内存中,然后i的值就是2,明明加了两次,却丧失了一个加一操作,这就是多线程环境下出现的问题。
为了解决上一个问题,JMM规定了八种同步操作:先看图后解释
Lock:加锁,作用于主内存的变量,作用是把一个共享变量标识为一个线程独占状态。
UnLock:解锁,作用于主内存变量,作用是把一个处于锁定状态的变量释放,然后可以被其他线程锁定。
read:读取,作用于主内存中的变量,作用是从主内存中读取出后面load操作要用到的变量。
load:载入,作用于主内存中的变量,把刚才read的值放入工作内存的副本中。
use:使用,作用于工作内存中的变量,当线程执行某个字节码指令需要用到相应的变量时,把工作内存中的变量副本传给执行引擎。
assign:赋值,作用于工作内存中的变量,把一个从执行引擎接收的值,复制给工作内存中的变量。
store:存储,作用于工作内存中的变量,把工作内存中的变量送到主内存,给后续的write使用。
write:写入,作用于主内存的变量,把store的工作内存中的变量值,写入主内存中。
同时,JMM还对这8种操作制定了一些规则,限制指令的执行:
1、read和load,store和write必须顺序执行,就是说必须是先read然后load,并且这两对中的每一对中的两个不能单独出现,就是说不能只出现read,也不能只出现load
2、不允许一个线程丢弃最近的assign操作,就是说工作内存中的变量改变后,必须同步到主内存
3、不允许一个线程没有发生任何的assign操作,就把工作内存中的变量同步到主内存
4、一个新的变量必须诞生于主内存,不允许工作内存使用一个没有初始化的变量,即use和stroe前只执行了assign和load操作
5、一个变量同一时刻,只允许一个线程对其lock,并且该线程可以对该变量加锁多次,释放锁需要执行相同次数的unlock,lock和unlock要成对出现
6、一个变量没有lock,不能unlock,并且一个线程不能unlock被其他线程锁住的变量,执行unlock前,必须把工作内存中的变量同步到主内存中
7、一个线程执行lock操作,需要清空工作内存,并且需要使用该变量之前,要重新执行load和assign操作