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();
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix