1、指令重排
JVM为优化执行效率对线程内的执行顺序进行重排,对单线程来说执行指令重排并不会影响程序从上到下执行的代码逻辑。但是在多线程的情况下,则可能会出现问题。
2、指令重排原则
程序顺序原则:一个线程内保证语义的串行性volatile规则:volatile变量的写,先发生于读
锁规则:解锁(unlock)必然发生在随后的加锁(lock)前
传递性:A先于B,B先于C 那么A必然先于C
线程的start方法先于它的每一个动作
线程的所有操作先于线程的终结(Thread.join())
线程的中断(interrupt())先于被中断线程的代码
对象的构造函数执行结束先于finalize()方法
3、代码示例(实际演示中没有演示出效果)
package com.thread.study;
public class OrderExample {
int a = 0;
boolean flag = false;
public void write(){
a = 1;
flag = true;
}
public void read(){
if(flag){
int i = a + 1;
System.err.println("i="+i+"a="+a+"flag="+flag);
}
}
public static void main(String[] args){
OrderExample order = new OrderExample();
//A线程执行write方法,但是无法保证 a=1执行在前,flag = true执行在后
Thread threadA = new Thread(new Runnable(){
@Override
public void run() {
order.write();
}});
//线程 B执行read方法
Thread threadB = new Thread(new Runnable(){
@Override
public void run() {
order.read();
}});
threadA.start();
threadB.start();
}
}
4、避免指令重排
指令重排是编译器的一种优化手段,但是在多线程中可能会影响到代码逻辑。如何避免指令重排可以通过同步的方式(性能问题)
package com.thread.study;
public class OrderExample {
int a = 0;
boolean flag = false;
public synchronized void write(){
a = 1;
flag = true;
}
public synchronized void read(){
if(flag){
int i = a + 1;
System.err.println("i="+i+"a="+a+"flag="+flag);
}
}
public static void main(String[] args){
OrderExample order = new OrderExample();
//A线程执行write方法,但是无法保证 a=1执行在前,flag = true执行在后
Thread threadA = new Thread(new Runnable(){
@Override
public void run() {
order.write();
}});
//线程 B执行read方法
Thread threadB = new Thread(new Runnable(){
@Override
public void run() {
order.read();
}});
threadA.start();
threadB.start();
}
}
网上看到指令重排会对懒汉-单例模式有影响,后续分析。。。。