Java - Happens-before relationship

Java - Happens-before relationship_第1张图片

Happens-before 关系是对在一个线程内执行的操作在另一个线程内的操作的可见性保证。

Happens-before 定义程序中所有操作的偏序关系。为了保证操作 Y 的执行线程能观察到操作 X 的结果(不管 X 和 Y 是否发生在不同的线程内),就必须在 X 和 Y 之间存在 Happens-before 关系。如果在两个操作之间缺少 happens-before 顺序,那么 JVM 会任意地对操作进行重排序(JIT 编译优化)。

Happens-before 不仅仅是在时序上对操作进行重排序,它也是对内存读写顺序的保证。两个线程执行内存的读写操作可以在时间上对相互间的操作保持一致,但是可能不能一致地观察到彼此的改变(内存一致性错误),除非它们之间存在 happens-before 关系。

那如何建立 happens-before 关系呢?

以下是 happens-before 的规则:

  • 单线程规则: 单个线程的所有操作都 happens-before 在同一线程中的后续操作
Java - Happens-before relationship_第2张图片
  • 锁定规则: 锁的 unlock(存在于 synchronized 方法或代码块)happens-before 对这个锁的后续获取操作

    Java - Happens-before relationship_第3张图片

  • volatile 变量规则:对 volatile 字段的写操作 happens-before 其后对这个字段的所有读操作。对 volatile 字段的读写操作具有和监视器类似的内存一致性效果,不过它实际上并没有去获取监视器或者锁

    Java - Happens-before relationship_第4张图片

  • 线程启动规则: 在一个线程中对 Thread.start() 的调用 happens-before 被其启动的线程。假设线程A 通过调用 threadB.start() 启动一个线程B 。那么在线程B 的 run 方法内的所有操作都能观察到线程A 调用 threadA.start() 所在的方法及在这之前(仅在线程A中)所执行的操作。

    Java - Happens-before relationship_第5张图片

  • 线程join规则:线程中的所有操作 happens-before 从这个线程的 join 成功返回的所有其他线程。假设线程A 调用 threadB.start() 启动一个新线程B,然后再调用 threadB.join() 。 线程A 会在 join() 处等待直到线程B 的 run 方法执行完毕。join 方法返回结果后,线程A 中的所有后续操作都可以观察到线程B的 run 方法内所有的操作都在它们之前执行

    Java - Happens-before relationship_第6张图片

  • 传递性 如果 A happens-before B, B happens-before C,那么 A happens-before C

补充

摘自《java并发编程实战》

  • 中断规则 当一个线程在另一个线程上调用 interrupt 时,必须在中断线程检测到 interrupt 调用之前执行(通过抛出 InterruptedException,或者调用 isInterrupted 和 interrupted)
  • ** 终结器规则** 对象的构造函数必须在启动该对象的终结期之前执行完成

你可能感兴趣的:(Java - Happens-before relationship)