java高并发处理机制-java处理高并发的框架
目录
前言
JMM 是一个虚拟的内存模型,它抽象了 JVM 的运行机制,让 Java 开发人员能更好的理解 JVM 的运行机制,它封装了 CPU 底层的实现,
让 Java 的开发人员可以更好的进行开发java高并发处理机制,不被底层的实现细节折磨。JMM 想表达的是,在某种程度上,你可以通过一些 Java 关键字让 Java 的内存模型达到一种强一致性。所以 JMM 和缓存一致性协议并不挂钩,本质上就没什么联系。
多线程-线程之间的通信
线程是指程序的一个指令执行序列,允许程序中存在多个线程。 在单 cpu 系统中,系统把 cpu 的时间片按照调度算法分配给各个线程java高并发处理机制,因此各线程实际上是分时执行的。
在多个CPU中, 同一个程序的不同线程可以被分配到不同的 cpu 上去执行。由于一个程序的各线程是在相同的地址空间运行的,因此设及到了如何共享内存, 如何通信等问题,这样便需要处理各线程之间的同步问题
线程的通信方式:
JMM内存模型
java采用的是共享内存并发模型
在java中,所有的实例域,静态域和数组元素都存储在堆内存中,堆内存在线程之间共享。局部变量,方法参数和异常处理器参数不会在线程之间共享,他们不会有内存可见性问题,也不受内存模型的影响。
Java 内存模型规定 :
工作内存是寄存器和高速缓存的抽象,就是把他们两者之前的流程抽象为一个工作内存。
java线程之间的通信由java内存模型(JMM)控制,JMM决定了一个线程对共享变量的写入何时对另一个线程可见。JMM定义了多线程和主内存之间的抽象关系:
线程之间的共享变量存储在主内存中每个线程都有一个私有的本地化内存本地内存中存储了该线程用以读/写共享变量的副本。
抽象抽象,说白了还是同一个东西,按照模块功能拆分了一下,线程是运行在CPU上面的,CPU运行线程时使用到的内存空间就是工作内存,而本地内存除了寄存器和CPU缓存还有其他的空间,例如写缓冲区等,所以本地内存是包含工作内存的,这两个内存是线程私有的
如上图示:
JAVA内存模型定义的八种原子操作
学习缓存一致性协议的时候,多CPU内线程共享的资源是通过MESI协议进行数据一致性的。Java内存的线程是如何进行一致性呢!!!
JMM定义了8种指令,它工作的时候就是通过这8种指令来操作内存的
lock(锁定):把主内存中的一个共享变量标记为一个线程独享的状态
unlock(解锁):把主内存的变量从线程独享的lock状态中解除出来
read(读取):把主内存的一个共享变量传输工作内存中
load(载入):把从主内存传输到工作内存的共享变量,赋值给工作内存中的变量副本
use(使用):把工作内存中的变量副本的值,传递给执行引擎CPU
assign(赋值):执行引擎(CPU)执行完之后,把修改过的变量值重新赋值给工作内存中的变量副本
store(存储):把工作内存中修改过共享变量的值传递到主内存中
write(写入):把传递到主内存中的变量值,重新写回给主内存的共享变量
比如线程A要执行一个x++的操作,可能要经历下面的过程:
read指令先把把主内存的一个共享变量传输本地内存中(官方抽象定义本地内存,又叫工作内存)执行load载入命令把共享变量赋值给本地内存中的变量副本当CPU内部的计算逻辑单元运行到了x++指令的时候,把工作内存中的变量副本的值,传递给执行引擎CPU进行执行执行完成x++的时候,使用assign命令,把最新的数据刷新到本地内存执行store命令,把工作内存中修改过共享变量的值传递到主内存中执行write命令,把传递到主内存中的变量值,重新写回给主内存的共享变量
比如在执行一个x++的操作期间,会执行到loc指令:那么在线程内部是如何执行的呢?
工作线程A操作该共享内存变量的时候,执行lock指令,主内存中的这个共享变量;同时告诉线程B这个共享变量我准备修改了,让它失效掉。
B线程的变量副本失效之后,运行时候用到,需要到主内存重新读取(执行read、load操作放入工作内存);发现该主内存的变量被锁定了,读取失败;此时相当于线程A拥有该变量的独享操作
线程A执行i++操作,经历上述说的(read、load、use、assign、store、write)指令之后;操作完成执行unlock释放锁定的这个内存变量
线程B这个时候再去主内存读取的时候,发现未被锁定,就可以重新读取了
线程安全之可见性、有序性、原子性