JMM
JMM(Java内存模型,Java Memory Model)本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过规范定制了程序中的各个变量的访问方式。
JMM关于同步的规定:
- 线程解锁前,必须把共享变量的值刷新回主内存。
- 线程加锁前,必须读取主内存的最新值到自己的工作内存。
- 加锁解锁必须是同一个锁。
特点:
- 原子性:即一个操作或多个操作在执行的过程中,要成功都成功,要失败都失败。
- 可见性:多个线程访问同一个变量时,当一个线程修改该变量时,其他线程可见。
- 有序性:保证程序运行的顺序是代码的顺序。 在java 内存模型中,为了效率,是允许编译器和处理器对指令进行重排序的,对单线程运行不会影响,但是会影响多线程运行结果。
happens-before
了解有序性后需要了解一下happens-before原则:
定义:
- 如果一个操作happens-before另一个操作,那么第一个操作的执行结果对第二个操作执行结果可见,而且第一个操作顺序在第二个之前
- 如果两个操作存在happens-before关系,并不意味着一定按照happens-before顺序执行。如果重排序后的运行的值和happens-before运行结果一样,那么这种重排序并不违法
规则(来源 《深入理解 Java 虚拟机》)
程序次序规则:一个线程内,按照代码顺序,书写在前面的操作,happens-before 于书写在后面的操作。
锁定规则:一个 unLock 操作,happens-before 于后面对同一个锁的 lock 操作。
volatile 变量规则:对一个变量的写操作,happens-before 于后面对这个变量的读操作。
传递规则:如果操作 A happens-before 操作 B,而操作 B happens-before 操作C,则可以得出,操作 A happens-before 操作C
线程启动规则:Thread 对象的 start 方法,happens-before 此线程的每个一个动作。
线程中断规则:对线程 interrupt 方法的调用,happens-before 被中断线程的代码检测到中断事件的发生。
线程终结规则:线程中所有的操作,都 happens-before 线程的终止检测,我们可以通过Thread.join() 方法结束