happens-before规则规定了对共享变量的写操作对其他线程的读操作可见,抛开happens-before规则,jmm不能保证一个线程对共享变量的写,对于其他线程对该共享变量的读可见
-
线程解锁m之前对变量的写,对于接下来对m加锁的其他线程对该变量的读可见
在线程t1解锁之前写入了x的值,t2对m加锁时读取到的x值就为t1写入的值
static int x; static Object m = new Object(); public static void main(String[] args) { new Thread(()->{ synchronized(m) { x = 10; } },"t1").start(); new Thread(()->{ synchronized(m) { System.out.println(x); } },"t2").start(); }
-
线程对volatile变量的写,对接下来其他线程对该变量的读可见
volatile static int x; public static void main(String[] args) { new Thread(()->{ x = 10; },"t1").start(); new Thread(()->{ System.out.println(x); },"t2").start(); }
-
线程start前对变量的写,对该变量开始后该变量的读可见
static int x; public static void main(String[] args) { x = 10; new Thread(()->{ System.out.println(x); },"t2").start(); }
-
线程结束前对变量的写,对其他线程得知它结束后的读可见
static int x; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { x = 10; },"t1"); t1.start(); t1.join(); System.out.println(x); }
-
线程t1打断t2(interrupt)前对变量的写,对其他线程得知t2被打断后对变量的读可见(t2.interrupted/t2.isInterrupted)
static int x; public static void main(String[] args) { Thread t2 = new Thread(()->{ while(true) { if(Thread.currentThread().isInterrupted()) { log.info("t2被打断后,{}",x); break; } } },"t2"); t2.start(); new Thread(()->{ Sleepy.sleep(1000); x = 10; t2.interrupt(); },"t1").start(); while(!t2.isInterrupted()) { Thread.yield(); } log.info("test,{}",x); }
-
对变量默认值(0,false,null)的写,对其他线程对该变量的读可见
-
具有传递性,如果x hb-> y 且y hb ->z 那么有 x hb->z,配合volatile的防指令重排
volatile static int x; static int y; public static void main(String[] args) { new Thread(()->{ y = 10; x = 20; },"t1").start(); new Thread(()->{ // x=20 对 t2 可见, 同时 y=10 也对 t2 可见 System.out.println(x); },"t2").start(); }