前提概要
java本身具有垃圾回收器这种智能的自动化管理内存功能之外,就是多线程的支持并发机制功能实现,线程之间的通信方式,java数据模型采用的是共享内存,此外还可以采用信号量等机制/套接字通信机制。
Java的并发采用“共享内存”模型,线程之间通过读写内存的公共状态进行通讯。多个线程之间是不能通过直接传递数据交互的,它们之间交互只能通过共享变量实现。
主要目的是定义程序中各个变量的访问规则。
JMM模型规定所有变量都存储在主内存,每个线程还有自己的工作内存。
1.线程工作内存中保存被该线程使用到的变量的拷贝(从主内存中拷贝过来),线程对变量的所有操作都必须在工作内存中执行,而不能直接访问主内存中的变量。
2.线程间无法直接访问对方工作内存变量,线程间变量值传递要通过主内存实现。
3.主内存主要对应Java堆中实例数据部分。工作内存对应于虚拟机栈中部分区域。
Intel的处理器的系统模型。如图所示:
主存和工作内存的交互方式
Java线程之间的通信由内存模型JMM(Java Memory Model)控制。
(1)JMM决定线程对变量的写入何时对另一个线程可见。
(2)线程之间共享变量存储在主内存中
(3)线程有一个私有的本地内存,里面存储了读/写共享变量的副本。
(4)JMM通过每个线程的本地内存之间的交互,提供内存可见性保证。
可见性和有序性:
(1)可见性:共享变量在多个本地内存中有副本时,如果本地内存修改了该变量的副本,其他变量应该能够看到修改后的值。
(2)有序性:保证线程的有序执行,保证线程安全。
工作内存和内存间交互操作:
lock(锁定):作用主内存的变量,把变量标识为一条线程独占状态。
unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
read(读取):作用于主内存变量,把主内存的一个变量读取到工作内存中,以便随后的load操作。(非必须)
load(载入):作用于工作内存,把read操作读取到工作内存的变量载入到工作内存的变量副本中。(非必须)
use(使用):作用于工作内存变量,把工作内存中变量值传递给一个执行引擎,虚拟机遇到一个使用到变量的指令时都会使用该指令
assign(赋值):作用于工作内存变量。把执行引擎接收到的值赋值给工作内存的变量,虚拟机遇到一个给变量赋值的指令时
store(存储):把工作内存变量的值传递给主内存。(非必须)
write(写入):把store操作的值入到主内存的变量中。(非必须)
注意:
1.不允许read、load、store、write操作之一单独出现
2.不允许一个线程丢弃assgin操作
3.不允许一个线程不经过assgin操作,就把工作内存中的值同步到主内存中
4.一个新的变量只能在主内存中生成
5.一个变量同一时刻只允许一条线程对其进行lock操作。但lock操作可以被同一条线程执行多次,只有执行相同次数的unlock操作,变量才会解锁
6.如果对一个变量进行lock操作,将会清空工作内存中此变量的值,执行引擎使用这个变量前,需要重新执行load或者assgin操作初始化变量的值。
7.如果变量没有被锁定,不允许对其执行unlock操作,也不允许unlock一个被其他线程锁定的变量
8.对变量执行unlock操作之前,需要将该变量同步回主内存中