作用
JMM(Java Memory Model)是java内存模型。用来屏蔽不同硬件不同操作系统访问内存的差异性,确保java程序在不同平台上能达到一致的内存访问效果。也就是同一个程序在不同的虚拟机上运行,得到的结果是一致的。
规范
在jmm规范中,所有的变量(不包括局部变量和方法参数)都存储在主内存中,每个线程都有自己的工作内存,工作内存中的变量是主内存该变量的拷贝。
线程不能直接读写主内存,只能操作自己工作内存中的变量,然后再同步到主内存,这样其它线程就能看到本次修改。
主内存是多个线程共享的,工作内存是线程私有的。线程间的通信必须通过主内存来完成
JMM三大特性
-
原子性:一个操作是不可分割,不可中断的,一个线程在执行时不会被其它线程干扰。java提供了synchronized关键字来保证原子性。
-
可见性:一个线程修改共享变量的值,其它线程能够立即知道。java是通过volatile关键字来提供可见性,另外final和synchronized关键字也能实现可见性。
-
有序性:可以使用synchronized或者volatile关键字保证多线程之间操作的有序性。volatile是通过内存屏障禁止指令重排序。synchronized代码块在多线程下是串行执行。
JMM八种内存操作
- lock(锁定):作用于主内存中的变量,把变量标识为线程独占的状态。
- read(读取):作用于主内存的变量,把变量的值从主内存传输到线程的工作内存中,以便下一步的load操作使用。
- load(加载):作用于工作内存的变量,把read操作主存的变量放入到工作内存的变量副本中。
- use(使用):作用于工作内存的变量,把工作内存中的变量传输到执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
- assign(赋值):作用于工作内存的变量,它把一个从执行引擎中接受到的值赋值给工作内存的变量副本中,每当虚拟机遇到一个给变量赋值的字节码指令时将会执行这个操作。
- store(存储):作用于工作内存的变量,它把一个从工作内存中一个变量的值传送到主内存中,以便后续的write使用。
- write(写入):作用于主内存中的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。
-
unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
JMM八种内存操作
happens-before原则
- 程序次序规则:在一个线程中,按照代码的顺序,前面的操作Happens-Before于后面的任意操作。
- volatile变量规则:对一个volatile变量的写操作,Happens-Before于后续对这个变量的读操作。
- 传递规则:如果A Happens-Before B,并且B Happens-Before C,则A Happens-Before C。
- 锁定规则:对一个锁的解锁操作 Happens-Before于后续对这个锁的加锁操作。
- 线程启动规则:如果线程A调用线程B的start()方法来启动线程B,则start()操作Happens-Before于线程B中的任意操作。
- 线程终结规则:线程A等待线程B完成(在线程A中调用线程B的join()方法实现),当线程B完成后(线程A调用线程B的join()方法返回),则线程A能够访问到线程B对共享变量的操作。
- 线程中断规则:对线程interrupt()方法的调用Happens-Before于被中断线程的代码检测到中断事件的发生。
- 对象终结原则:一个对象的初始化完成Happens-Before于它的finalize()方法的开始。
网友评论