Happens-Before 规则是什么

370 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

这个其实这个 happen-before 是 JVM 定义一个规则。appens-before:A 事件 happens-before B事件就是 A 事件先行发生于 B 事件,这样理解不准确,定义为hb(A, B)。在 JVM 内存模型中,happens-before 的意思是前一个操作的结果可以被后续操作获取。

为什么需要 happens-before

Java 虚拟机在进行代码编译优化时,会出现指令重排序问题,为了避免编译优化对并发编程安全性的影响,Java 虚拟机需要 happens-before 规则限制或禁止编译优化的场景,保证系统并发的安全性。

happens-before 规则

程序序顺序的规则

也就是说一个线程里面的每一个操作,happens-before 发生于什么该线程中的任意后续操作之前,其实聊的是什么?这些操作聊的应该是可见性的问题。也就是说对于线程 happening-before 之前的这些操作,对后面的这个操作进行。重点说的就是可见性的问题,

监视器的规则

对一个锁的解锁, happened-before于随后对这个锁的加锁。如果说你先解锁了,然后再加锁,这什么意思啊。就是无论是在单线程环境还是多线程环境,对于同一个锁来说,一个线程对这个锁解锁之后,另一个线程获取了这个锁都能看到前一个线程的操作结果。

volatile变量规则

volatile 变量的写了和读。volatile 的一个写操作,那么 happen-before 于任意后续对一个 volatile 变量的读。也就是说后面 volatile 读,那么不会重排序到我的 volatile 变量写之前。也就是说它写了,你才能读。读到的就是写到的那个变量。这是可见性的问题。

再往下传递性

这个简单的,就是happens-before原则具有传递性,如果 a happens before b,b happens before c, 那么 a happens before c 这是传递性。

线程的启动规则

在主线程 A 执行过程中,启动子线程 B,那么线程 A 在启动子线程 B 之前对共享变量的修改结果对线程 B 可见。你只能启动之后才能后续操作。这个第一个规则是不是很像,你说我对这个线程结束了,他执行完了这些操作,一定会对我后面要去读我们这个线程执行的一个操作的这些变量都具有可见性。

线程终止规则

我们可以通过 Thread.join 方法来进行等待结束。Thread.isAlive 用来检测线程已经结束。那什么意思?假如你用这个等的方法执行,然后你再判断它它可不可能 Thread.isAlvie 跑到了 Thread.join 里边去,不可能。也就是说你把一个线程你等着它停止了,那么你查这个返回值,你的 alive,那一定是已经终止了。而不可能说你是 aisAlive 是没终止,但是线程已经终止了,对不对?它有一个严格的顺序性和可见性。也就是说线程死亡终结的这个状态对后面的这个是否可见,一定要记住,这是可见性问题。

线程中断的操作

这个也很容易理解。对线程interrupt()方法的调用先行发生于被中断线程代码检测到中断事件的发生,可以通过Thread.interrupted()检测到是否发生中断。

对象终结规则

这个也简单的,就是一个对象的初始化的完成,也就是构造函数执行的结束一定 happens-before它的finalize()方法。