内存模型:为了能够保证共享内存的原子性,可见性,有序性,内存模型定义了共享内存系统中多线程程序读写操作行为的规范。
原子性:指的是某个操作在CPU上执行时,CPU不可以中途暂停执行该操作然后去调度其它操作,这个操作要么全部执行完,要么不执行。
可见性:指的是当多个线程访问同一个变量时,某个线程修改了该变量的值,其它线程能够立即知道修改的值。
有序性:指的是程序的执行顺序要按照代码的先后顺序执行。
Java内存模型(JMM):指的是一种符合内存模型规范,屏蔽了各种硬件和操作系统差异的,保证了java程序在各种下对内存的访问都能保证效果一致的机制及规范。
Java内存模型规定了所有变量都存储在主内存中,每个线程都有自己的工作内存,线程的工作内存中保存了该线程需要用到的变量的主内存副本拷贝,线程对变量的操作都必须在工作内存中进行,而不能直接读写主内存,不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步。JMM就作用于工作内存和主存之间数据同步过程。他规定了如何做数据同步以及什么时候做数据同步。
JMM是一种规范,目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。目的是保证并发编程场景中的原子性、可见性和有序性。
原子性:
在Java中,为了保证原子性,提供了两个高级的字节码指令monitorenter
和monitorexit
。这两个字节码,在Java中对应的关键字就是synchronized
。
可见性:
Java内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值的这种依赖主内存作为传递媒介的方式来实现的。Java中的volatile
关键字提供了一个功能,那就是被其修饰的变量在被修改后可以立即同步到主内存,被其修饰的变量在每次是用之前都从主内存刷新。因此,可以使用volatile
来保证多线程操作时变量的可见性。除了volatile
,Java中的synchronized
和final
两个关键字也可以实现可见性。
有序性:
在Java中,可以使用synchronized
和volatile
来保证多线程之间操作的有序性。volatile
关键字会禁止指令重排。synchronized
关键字保证同一时刻只允许一条线程操作。