happens-before规则:

happens-before规定了对共享变量的写操作对其他线程的读操作可见,它是可见性与有序性的一套规则总结,抛开以下happens-before规则,JMM并不能保证一个线程对共享变量的写,对于其他线程对该共享变量的读可见

1.线程解锁m之前对变量的写,对于接下来对m加锁的其他线程对该变量的读可见
  1. static int x;
  2. static Object m = new Object();
  3. new Thread(()->{
  4. synchronized(m){
  5. x = 10;
  6. }
  7. },"t1").start();
  8. new Thread(()->{
  9. synchronized(m){
  10. System.out.println(x);
  11. }
  12. },"t2").start();

2.线程对volatile变量的写,对接下来其他线程对该变量的读可见
  1. volatile static int x;
  2. new Thread(()->{
  3. x = 10;
  4. },"t1").start();
  5. new Thread(()->{
  6. System.out.println(x);
  7. },"t2").start();

3.线程start前对变量的写,对该线程开启后对该变量的读可见
  1. static int x;
  2. x = 10;
  3. new Thread(()->{
  4. System.out.println(x);
  5. },"t2").start();

4.线程结束前对变量的写,对其它线程得知它结束后的读可见(比如其他线程调用isAlive或join等待它结束)
  1. static int x;
  2. Thread t1 = new Thread(()->{
  3. x = 10;
  4. },"t1");
  5. t1.start();
  6. t1.join();
  7. System.out.println(x);

5.线程t1打断t2前对变量的写,对于其他线程得知t2被打断后对变量的读可见
  1. static int x;
  2. public static void main(String[] args) {
  3. Thread t2 = new Thread(()->{
  4. while(true) {
  5. if(Thread.currentThread().isInterrupted()) {
  6. System.out.println(x);
  7. break;
  8. }
  9. }
  10. },"t2");
  11. t2.start();
  12. new Thread(()->{
  13. sleep(1);
  14. x = 10;
  15. t2.interrupt();
  16. },"t1").start();
  17. while(!t2.isInterrupted()) {
  18. Thread.yield();
  19. }
  20. System.out.println(x);
  21. }

6.对变量默认值(0,false,null)的写操作,对其他线程对该变量的读可见

7.具有传递性
  1. volatile static int x;
  2. static int y;
  3. new Thread(()->{
  4. y = 10;
  5. x = 20;
  6. },"t1").start();
  7. new Thread(()->{
  8. // x=20 对 t2 可见, 同时 y=10 也对 t2 可见
  9. System.out.println(x);
  10. },"t2").start();