理解并发程序执行 (Peterson算法、模型检验与软件自动化工具
本次课回答的问题
- Q: 如何理解各种并发程序?
Take-away message
- 并发程序 = 状态机
- 线程共享内存
- 每一步非确定选择线程执行
- 画状态机就对了
- 当然,用工具帮你画 (model checker)
画状态机
初始状态
pc1 pc2 x y turn
(1 1 0 0 A)
T1执行
会abort
#include "thread.h" #define A 1 #define B 2 atomic_int nested; atomic_long count; void critical_section() { long cnt = atomic_fetch_add(&count, 1); assert(atomic_fetch_add(&nested, 1) == 0); atomic_fetch_add(&nested, -1); } int volatile x = 0, y = 0, turn = A; void TA() { while (1) { /* PC=1 */ x = 1; /* PC=2 */ turn = B; /* PC=3 */ while (y && turn == B) ; critical_section(); /* PC=4 */ x = 0; } } void TB() { while (1) { /* PC=1 */ y = 1; /* PC=2 */ turn = A; /* PC=3 */ while (x && turn == A) ; critical_section(); /* PC=4 */ y = 0; } } int main() { create(TA); create(TB); }
习题:证明 Peterson 算法正确,或给出反例
进入临界区的情况
如果只有一个人举旗,他就可以直接进入
如果两个人同时举旗,由厕所门上的标签决定谁进
手快有(被另一个人的标签覆盖)、手慢无
一些具体的细节情况
A 看到 B 没有举旗
B 一定不在临界区
或者 B 想进但还没来得及把 “A 正在使用” 贴在门上
memory ordering
A 看到 B 举旗子
A 一定已经把旗子举起来了
https://jyywiki.cn/OS/2022/slides/4.slides#/1/3
Peterson 算法
正确性不明的奇怪尝试 (Peterson 算法)
A 和 B 争用厕所的包厢
- 想进入包厢之前,A/B 都要先举起自己的旗子
- A 确认旗子举好以后,往厕所门上贴上 “B 正在使用” 的标签
- B 确认旗子举好以后,往厕所门上贴上 “A 正在使用” 的标签
- 然后,如果对方的旗子举起来,且门上的名字不是自己,等待
- 否则可以进入包厢
- 出包厢后,放下自己的旗子
- 处理器默认不保证 load + store 的原子性
失败的尝试
int locked = UNLOCK;
void critical_section() {
retry:
if (locked != UNLOCK) {
goto retry;
}
locked = LOCK;
// critical section
locked = UNLOCK;
}
和山寨 alipay.c 完全一样的错误
【理解并发程序执行 (Peterson算法、模型检验与软件自动化工具) [南京大学2022操作系统-P4]】https://www.bilibili.com/video/BV15T4y1Q76V