“在共享内存系统中,信号量是带非负整数状态 $S\in\mathbb N$ 的同步对象。其两个基本原子操作通常记为 $P/V$、 或 :”
形式陈述 ​
设共享对象由一台抽象状态机描述。称对象上的一个操作是原子的,若在抽象层面的并发对象历史中,它把对象从一个状态不可分割地转移到另一个状态:任何其他线程都观察不到它的中间状态。等价的表述是,每个原子操作可以被赋予一个位于其调用与返回之间的单一时刻(线性化点),仿佛整个效果在该瞬间一次性发生;操作之间的可见效果与按这些时刻排成的顺序执行一致。原子性是对"抽象历史中的粒度"的规定,与实现层的步数无关:一个操作可以由多条机器指令实现,只要并发观察者无法看穿其内部即可。
直觉
并发推理的根本困难在于交错:
例子与边界
正例:原子读写寄存器保证读操作永远返回某次完整写入的值,不会出现"撕裂值"。反面对照能看清它防住了什么:在只支持 32 位原子访问的机器上用两条指令写一个 64 位数,并发读者可能读到"前一半旧值、后一半新值"拼成的从未被写入过的数——原子性排除的正是这种中间状态泄露。
边界情形之一是复合操作:先原子地读
原子 fetch_add 可避免两个线程同时递增时丢失更新;普通“读计数、加一、写回”由三步组成,可能发生竞态。两个原子变量分别更新并不能保证读者只看到“两者都旧或都新”。在弱内存模型下,原子操作还需选择 acquire/release 等顺序语义。
推论与应用
原子操作是同步对象的实现基础:互斥锁可用原子测试与更新转移所有权,信号量实现则需原子维护许可计数及等待队列状态,引用计数依赖原子增减,无锁数据结构以比较并交换为骨架并追求lock-free 进展。这些对象各自还规定所有权、阻塞或唤醒语义,不能从“底层更新是原子的”直接推出完整接口正确性。
在正确性理论中,为每个操作指定线性化点是证明线性一致性的标准手法,原子操作因此连接实现与顺序规格。不同原子原语的表达力并不相同;它们能为多少参与者实现何种对象,由共识数层级统一刻画。
参考资料
- Maurice Herlihy and Nir Shavit, The Art of Multiprocessor Programming, rev. 1st ed., Morgan Kaufmann, 2012,Chs. 1–18。
- Hagit Attiya and Jennifer Welch, Distributed Computing: Fundamentals, Simulations, and Advanced Topics, 2nd ed., Wiley, 2004,Chs. 1–18。