8种基本操作
- lock(锁定)
作用于主内存的变量,把一个变量标识为一条线程独占状态。
- unlock(解锁)
作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定
- read(读取)
作用于主内存的变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的Load
动作使用
- load(载入)
作用于工作内存的变量,它把Read
操作从主内存中得到的变量值放入工作内存的变量副本中
- use(使用)
作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎
- assign(赋值)
作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量
- store(存储)
作用于工作内存的变量,把工作内存中的一个变量的值传递到主内存中,以便随后的Write
操作
- write(写入)
作用于主内存的变量,它把Store
操作从工作内存中一个变量的值传送到主内存中的变量中。
对应的同步规则
Java内存中定义的同步规则流程如上图所示,该流程是这样的:
位于主内存
中的对象,先被线程Lock
之后,执行Read
操作,将其从主内存
中读取出来,然后执行Load
操作,拷贝一份副本到工作内存
中,在工作内存
中通过Use
操作被Java线程
使用,在Java线程
处理结束后,对象的状态发生了变化,而状态变化后的对象通过执行Assign
操作,将改变后的状态值同步到工作内存
中,在工作内存
中,通过执行Store
操作,将改变后的值Save
到源对象,执行Save
后的源对象然后通过Write
操作,将源对象写入到主内存
中,在所有的上述操作完成后,该线程执行Unlock
操作,释放此被锁定的对象。
这里需要注意的是Read
、Write
操作的是源对象,而Load
、Store
操作的是副本对象,除了这些之外,我们还需要注意以下一些同步规则:
-
如果要把一个变量从主内存中复制到工作内存,就需要按顺序地执行
Read
和Load
操作,如果把变量从工作内存同步回主内存,就要按顺序地执行Store
和Write
操作。但Java
内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行 -
不允许
Read
和Load
、Store
和Write
操作之一单独出现 -
不允许一个线程丢弃它最近的
Assign
操作,即变量在工作内存中改变了之后必须同步到主内存中。 -
不允许一个线程无原因地(没有发生过任何
Assign
操作)把数据从工作内存同步回主内存中 -
一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(
Load
或Assign
)的变量,即就是对一个变量实施Use
和Store
操作之前,必须先执行过了Assign
和Load
操作 -
一个变量在同一时刻只允许一条线程对其进行
Lock
操作,但Lock
操作可以被同一条线程重复执行多次,多次执行Lock
后,只有执行相同次数的Unlock
操作,变量才会被解锁。Lock
和Unlock
必须成对出现 -
如果对一个变量执行
Lock
操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行Load
或Assign
操作初始化变量的值 -
如果一个变量事先没有被
Lock
操作锁定,则不允许为它执行Unlock
操作;也不允许去Unlock
一个被其它线程锁定的变量 -
对一个变量执行
Unlock
操作之前,必须先把此变量同步到主内存中(执行Store
和Write
操作)