happens-before规则

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

  • 线程解锁m之前对变量的写,对于接下来对m加锁的其它线程对该变量的读可见
static int x;
static final Object m = new Object();

new Thread(()->{
    synchronized(m){
        x = 10;
    }
},"t1").start();

new Thread(()->{
    synchronized(m){
        System.out.println(x);
    }
},"t2").start();
  • 线程对volatile变量的写,对接下来其它线程对该变量的读可见。
volatile static int x;
new Thread(()->{
    x = 10;
},"t1").start();

new Thread(()->{
    System.out.println(x);
},"t2").start();
  • 线程start前对变量的写,对该线程开始后对该变量的读可见
static int x;
x=10;
new Thread(()->{
    System.out.println(x);
},"t2").start();
  • 线程结束前对变量的写,对其它线程得知它结束后的读可见(比如其它线程调用t1.isAlive()或t1.join()等待它的结束)
static int x;
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()){
                System.out.println(x);
                break;
            }
        }
    },"t2");
	t2.start();
    
    new Thread(()->{
        sleep(1);
        x = 10;
        t2.interrupt();
    },"t1").start();
    
    while(!t2.isInterrupted()){
        Thread.yield();
    }
    System.out.println(x);
}
  • 对变量默认值(0, false, null)的写,对其它线程对该变量的读可见

  • 具有传递性,如果 x hb-> y 并且 y hb-> z 那么有 x hb-> z, 配合volatile 发防指令重排有下面例子

volatile static int x;
static int y;
new Thread(()->{
    y = 10;
    x = 20;
}, "t1").start();

new Thread(()->{
    // x = 20 对t2可见,同时 y=10 也对 t2可见
    System.out.println(x);
},"t2").start();
posted @   fjhnb  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示