“通用构造的核心是把并发操作转化为一串待决定的状态机步骤。各进程提出下一项操作,利用第 $k$ 个共识对象唯一决定序列位置 $k$ 的内容,再按共同前缀计算返回值;帮助机制使其他进程能够接手已…”
形式陈述 ​
一个调用的发起者停住后,其他进程能否完成它尚未做完的工作?对并发对象,帮助机制允许进程推进他人的已公布调用,或发布可被其他调用复用的有效结果。它是一族构造方法,不是一项独立一致性条件,也不是看到 help() 函数名就成立的进展保证。
以描述符帮助为例,每次请求有唯一身份
- 帮的是谁? 描述符身份在仍可能被引用期间不能被另一调用复用,否则旧 helper 会误帮新请求。
- 何时唯一生效? 多个 helper 可以重复计算候选结果,但抽象状态转移只能提交一次;操作不能因为换了执行者而重复产生效果。
- 怎样知道完成? 请求结果必须与那一次提交匹配,拥有者恢复后能读取或重建它,不能重新执行操作来“补回复”。
以线性一致性为安全目标时,提交点可以由 helper 执行,仍须落在被帮助调用的调用与返回之间。以wait-free为进展目标时,还必须证明每个持续执行的请求在有界帮助流程中得到处理。帮助能力只解决“别人能接手”,选择规则还要解决“这次请求不会永远被跳过”。
直觉
帮助把操作从“这个线程正在做的私有过程”变成“任何参与者都能辨认和推进的公开任务”。描述符像附有编号的工单:原处理人可以离开,接手者必须知道工单是哪一件、做到哪一步、是否已经完成,以及该回报哪个结果。
与锁不同,helper 不等待原持有者恢复。与盲目重试也不同,helper 不重新制造一份外部效果。安全帮助的关键是把可重复的准备工作与不可重复的抽象提交分开,并让所有人认可同一个提交证据。
例子与边界
用顺序日志帮助一次递增 ​
考虑初值为 fetch_increment():一次调用把计数器加一,返回递增前的值。三个进程
若日志的前三个位置决定为
| 已提交位置 | 请求 | 之前状态 | 新状态 | 该请求结果 |
|---|---|---|---|---|
| 1 | 0 | 1 | 0 | |
| 2 | 1 | 2 | 1 | |
| 3 | 2 | 3 | 2 |
共识的作用是让同一位置只有一个后继,描述符状态及日志不变式的作用是让同一请求只出现一次。拥有者和 helper 可分别计算“状态 fetch_increment()。
为什么先做副作用、再标记完成不安全 ​
一种看似简单的实现是:helper 读到 d.done == false,先递增共享计数器,再执行 CAS(d.done, false, true)。让两个 helper 都读到 false,随后分别递增,最后只有一个 CAS 成功。一次请求已产生两次递增;失败的 CAS 无法撤销先前效果。若赢家在递增后、写入结果前停住,其他人还可能不知道该返回哪个旧值。
修复不能只加一个完成标志。提交协议必须使“哪次状态转移归属哪个请求”可被唯一识别:例如通过共识决定日志后继,或在适当原语和状态表示下原子地安装包含请求身份与结果的状态。内存回收还必须保证旧 helper 不会持有已重用的描述符地址;本页例子假设描述符和日志项在仍可能被访问时不回收。
有帮助仍可能饥饿 ​
若每次日志竞争总优先挑最快进程的新请求,慢请求
Herlihy 的通用构造按日志序号轮转优先考察一个进程的公告;该进程有未提交请求时优先帮助它,否则才推进自己的候选。优先规则、公告与已接入链的状态不变式共同给出有限轮次界,不是“偶尔帮别人一次”就足够。原文 §4.1 Theorem 14 给出至多
推论与应用
共识数与 wait-free 层级中的通用构造用唯一排序解决安全性,用轮转帮助解决请求不会永久落后的进展问题。具备足够强的原语只说明这种构造存在,不能替代具体实现的提交与步骤界证明。
原子快照提供另一种帮助:更新者把自己已取得的完整视图与新值一起发布,扫描者在合适的版本证据下复用视图。这里没有替别人插入操作日志,仍需证明被复用结果在接收者的调用区间内有效。两类帮助共享的原则是公开足够证据,让一个调用的完成不依赖某个特定进程继续运行。
自测:在递增例子的第三项已经决定后,两个 helper 同时准备把结果
参考资料
- Maurice Herlihy, “Wait-Free Synchronization”, ACM Transactions on Programming Languages and Systems 13(1), 1991, pp. 124–149,§4.1、Figure 14、Theorem 14;§4.2 另讨论内存管理。
- Yehuda Afek, Hagit Attiya, Danny Dolev, Eli Gafni, Michael Merritt, and Nir Shavit, “Atomic Snapshots of Shared Memory”, Journal of the ACM 40(4), 1993, pp. 873–890,§3 的视图帮助构造。