Skip to content

Happens-before 关系

Happens-before · Causal order

由程序顺序及模型规定的通信或同步边生成的事件因果严格偏序。

条目类型
定义

形式陈述

固定一次合法执行的事件集合 E。模型先给出若干基本顺序边:同一进程或线程的程序顺序 <po;消息模型中的发送—接收边 <msg;共享内存语言中的 synchronizes-with 边 <sw,例如某次 release 写被 acquire 读观察到,或一次 unlock 与随后成功的 lock 配对。具体模型可以只采用其中一部分,不能把未由规范声明的墙上时间或缓存传播自行加边。

R0={(a,b)E×E:a<pob  a<msgb  a<swb}.

Happens-before 关系 <hbR0 的传递闭包:

a<hbbk1, e0,,ekE,a=e0R0e1R0R0ek=b.

合法执行要求这些生成边无环,因此 <hb 具有传递性和非自反性,是严格偏序。它的自反闭包

ahbba=b  a<hbb

才是偏序的非严格形式。对两个不同事件 a,b,若

¬(a<hbb)¬(b<hba),

则称它们在该模型的 happens-before 意义下并发。这个定义只说二者不可比较,不保证其内存效果可交换。

直觉

Happens-before 记录可证明的信息流。程序顺序让同一线程的前一步影响后一步,消息接收携带发送之前的知识,同步操作把一个线程先前的写入交给另一个线程。传递闭包再把这些局部证据串成跨线程、跨节点的因果链。

它不是物理时间轴。两个事件即使在测量上先后相隔很久,只要模型没有程序、通信或同步路径,仍可能不可比;反过来,某些语言允许编译器重排机器指令,却仍要求抽象执行保持规定的 happens-before。分析必须始终说明关系属于哪一层。

例子与边界
蓝色消息箭头与进程内顺序生成因果链;b 与 e 不可比较,因此并发。

消息执行中,进程 P 先执行 a,再发送 m;进程 Q 接收 m 后执行 b,于是

a<hbsend(m)<hbrecv(m)<hbb,

a<hbb。若进程 R 独立执行 c,且没有消息链把 cb 相连,则 b,c 不可比;日志系统可以选择先显示任一个,但不应把所选顺序冒充因果事实。

共享内存中,线程 P 先普通写 data = 42,再以 release 语义写 ready = true;线程 Q 的 acquire 读若从这次 ready 写取得 true,便有

WP(data,42)<poWPrel(ready,1)<swRQacq(ready,1)<poRQ(data).

所以数据写 happens-before 数据读。若 acquire 读没有观察该 release 写,或 ready 只是普通变量,所需 synchronizes-with 边可能不存在;仅凭读到了数值 true 不能跨语言模型自行补边。

语言模型还可能规定单个原子位置的 modification order、Java 同步动作的 synchronization order,或所有顺序一致原子的某个总序。这些附加次序不等于 happens-before 本身;只有规范指定的边才参与生成 <hb。同样,给日志任意选择一个全序只是偏序的线性扩张,不会把原本并发的事件变成因果相关。

推论与应用

Lamport 时钟保证 a<hbb 时标量时间递增,但逆命题不成立;向量时钟在固定成员、可靠事件传播等标准假设下可精确判定偏序。一致切片取 happens-before 的向下闭集,因果广播则让交付顺序保持消息因果。

数据竞争用模型特定的 happens-before 判断冲突普通访问是否未排序;不可比的只读访问却不会因此成为 race。偏序约简还要求动作独立与交换,不能仅从两个事件无因果路径就推出交换执行保持所有观察。

参考资料
  • Leslie Lamport, “Time, Clocks, and the Ordering of Events in a Distributed System,” Communications of the ACM 21(7), 1978, pp. 558–565。
  • Nancy A. Lynch, Distributed Algorithms, Morgan Kaufmann, 1996,§6.2。
  • Hans-J. Boehm and Sarita V. Adve, “Foundations of the C++ Concurrency Memory Model,” PLDI 2008, pp. 68–78。
关系图谱15 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组