重排序
什么是重排序
编译器和处理期为了提高程序的运行性能,对指令进行重新排序。
数据依赖性 as-if-serial
数据依赖性
1.写后读
2.读后写
3.写后写
指令重排序:
编译器重排序和处理器重排序
public class Demo { private int a; private boolean flag; public void writer(){ a = 1; flag = true;
// a , flag 没有数据依赖性,
//因此处理期会对这两行进行指令重排序
} public void reader(){ if(flag){ int b = a +1; System.out.println(b); } } }
happens-before
happen-before 是用来指定两个操作之间的执行顺序,提供跨线程的内存可见性。
在java内存模型中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作必然存在happens-before关系。
happen-before规则
程序顺序规则
监视器锁规则
volatile变量规则
传递性
Start规则
join规则
程序顺序规则:
单个线程中的每个操作,总是前一个操作happens-before于该线程中的任意后续操作
监视器规则
对同一个锁解锁,总是happen-before于随后对这个锁加锁
例: 1 happensbefore 2
1 public class Demo { 2 private Lock lock = new ReentrantLock(); 3 4 public void a(){ 5 lock.lock(); 6 7 lock.unlock(); //1.解锁 8 9 } 10 11 public void b(){ 12 lock.lock(); //2.加锁 13 14 15 lock.unlock(); 16 17 } 18 }
volatile变量规则
对一个volatile域的写,happens-before于任意后续对这个volatile域的读
传递性
a happensbefore b
b happensbefore c
..
a happensbefore c
start规则
1 happensbefore 2
1 public class Demo { 2 3 public void a(){ 4 System.out.println("a");//1.启动另外一个线程 5 new Thread(new Runnable() { 6 @Override 7 public void run() { 8 System.out.println("b");//2 9 } 10 }).start(); 11 } 12 13 }
Join规则
与start规则相反
主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束