# Happens-Before

在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。其描述的是可见性问题

操作之间存在Happens-Before关系, 并不意味着按照Happens-Before规则的顺序来执行, 在重排序之后, 执行结果与Happens-Before规则执行结果一致即可.

# 介绍几种HB规则

这里只列举出与Programmer相关的规则

# 程序执行的顺序性规则

在一个线程中, 前面的操作Happens-Before后面的操作

# volatile变量规则

对一个volatile变量的写操作一定Happens-Before其后面对这个变量的读操作

# 传递性规则

若A Happens-Before B, 且B Happens-Before C, 则A Happens-Before C.

# 锁的规则

对一个锁的解锁操作Happens-Before后面对这个锁的加锁

# 线程启动规则

主线程在启动子线程前的所有操作Happens-Before于子线程的任意操作

# 线程中断规则

对线程interrupt()方法的调用Happens-Before于被中断线程的代码检测到中断事件的发生

# 线程等待规则

它是指主线程 A 等待子线程 B 完成(主线程 A 通过调用子线程 B 的 join() 方法实现),当子线程 B 完成后(主线程 A 中 join() 方法返回),主线程能够看到子线程的操作。当然所谓的“看到”,指的是对共享变量的操作。

# 对象终结规则

一个对象的初始化完成Happens-Before于他的finalize()方法的开始

# 场景&案例

# 案例1

下面的案例代码reader()方法中, 通过if(v)判断后, 能否读到x=42?

此时应用了Happens-Before规则中的程序执行的顺序性规则volatile变量规则传递性规则

说明一下此处传递性规则的体现. 由于x=42Happens-Beforev=true, 且v=trueHappens-Before读v, 因此根据传递性规则所述, 则x=42Happens-Before读x.

public class TT {
    int x = 0;
    volatile boolean v = false;
    public void writer() {
        x = 42;
        v = true;
    }
    public void reader() {
        if (v) {
            System.out.println(x);
        }
    }
}
修改于: 8/11/2022, 3:17:56 PM