指令重排序
Java 语言规范规定了JVM线程内部维持一种类似串行语义:只要程序的最终结果与在严格串行环境中执行的结果相同,指令的执行顺序可以与代码的顺序不一致。这个技术叫指令的重排序。指令重排序存在的意义在于:JVM 能够根据处理器的特性(CPU的多级缓存系统、多核处理器等)重新排序机器指令,使机器指令更符合CPU的执行特点,最大限度的发挥机器的性能。
Happens-before规则
Java内存模型(JMM)为程序中所有操作定义了一个偏序关系,称为Happens-Before,保证可见性。
要想操作B的线程看到操作A的结果(无论A和B是否在一个线程中执行),那么A和B之间一定要满足Happens-Before关系。
如果两个操作之间没有Happens-Before关系,那么JVM可以对它们任意地重排序,可能产生奇怪的操作结果。
Happens-Before规则包括:
1. 程序顺序规则:同一个线程中的每个Action都必须happens-before出现在其后的任何一个Action。
2. 监视器锁规则:在监视器锁上的unlock操作必须happens-before 同一监视器上的lock操作。
3. volatile变量规则:对一个volatile变量的写操作必须happens-before对该变量的读操作。
4. 线程启动规则:在线程上start()方法的执行必须happes-before在该线程中执行任何其他操作。
5. 线程终止规则:线程中的任何操作都happens-before其他线程检测到该线程已经结束,或者从Thread.join()方法返回,或者调用Thread.isAlive()时返回false。
6. 线程中断规则:一个线程对另一个线程interrupt()方法的调用必须happens-before在被中断线程的代码检测到interrupt()调用。
7. 终结器规则:一个对象的初始化完成(构造函数执行结束)happens-before启动该对象的finalize()方法。
8. 传递性:如果操作A happens-before操作B,操作B happens-before操作C,那么一定A happens-before操作C。
示例: