背景

并发编程:从入门到放弃

  • 入门:threads.h
  • 放弃:原子性、顺序、可见性的丧失

但我们还得写并发程序啊!

  • 多处理器、多线程编程
  • GPU 编程
  • ……

本次课内容与目标

用状态机理解程序

  • Tower of Hanoi

用状态机模型理解并发程序

  • Peterson 算法

程序的阅读理解:实践

例子:汉诺塔

还记得第一次学的时候被汉诺塔支配的恐惧?

  • 面试题:把下面的程序转换成非递归

void hanoi(int n, char from, char to, char via) {
  if (n == 1) printf("Move #1 %c -> %c\n", from, to);
  else {
    hanoi(n - 1, from, via, to);
    printf("Move #%d %c -> %c\n", n, from, to);
    hanoi(n - 1, via, to, from);
  }
}

递归到非递归的转换

程序 = 状态机

  • hanoi(3, 'A', 'C', 'B') 到底是如何运行的?

“原始” 的模型 $(M, R)$ 对人类模拟执行太不友好了

  • 定义函数调用栈帧
    • PC: 下次执行的语句
    • 局部变量 (包括参数)
  • hanoi(2, 'A', 'B', 'C') 的 operational semantics
    • 当前栈帧 PC + 1
    • 创建新的栈帧 (PC 为第一条语句)
  • hanoi.c
    • 百度搜得的代码惨不忍睹,千万不要再用百度了

并发程序的阅读理解:实践

例子:互斥算法

希望实现 lock/unlock,保证

  • 假设编译器和硬件保证了顺序和可见性
  • 实现一段任意长代码的原子性
void do_sum() {
  for (int i = 0; i < n; i++) {
    lock(); // 保证顺序、原子性、可见性
    // critical section; 临界区
    sum++;
    unlock();
  }
}

Peterson 算法:实现 2 人的互斥

假设你和你舍友的行动速度都太快了,必须有一个机制保证你们无法同时进入 WC

  • 一个人瞬间只能完成
    1. 举起/放下自己手里的旗
    2. 向厕所门上贴一个标签 (覆盖之前贴的任何内容)
    3. 查看旗或标签的状态
  • 想上厕所的人
    1. 举起自己的旗
    2. 贴上有对方名字的标签 (谦让对方)
    3. 当对方没有举旗或标签写着自己名字时,进入 WC
    4. 出 WC 时放下旗子

Peterson 算法:代码

int turn, x = 0, y = 0;

void thread1() {
  x = 1; turn = T2;
  while (y && turn == T2) ;
  // critical section
  x = 0;
}

void thread2() {
  y = 1; turn = T1;
  while (x && turn == T1) ;
  // critical section
  y = 0;
}

(假设插入了 barrier 和 fence 指令)

为 Peterson 算法构造状态机

Prove by brute force:演示

  • 为每个线程构造简化的状态机
  • 并发程序状态:$(PC_1, PC_2, x, y, turn)$

如何证明 Peterson 算法的正确性?

  • 两种正确性
    • safety: 坏事情永远不会发生
      • $(X, X, *, *, *)$ 状态永远不会到达
    • liveness: 好事情永远会发生
      • 给两个线程有限步,一定有一个能进入状态 $X$

Peterson 算法:忘了它

忘记它的理由

  1. 只能用于两个线程的互斥
    • 多线程的扩展:filter lock; 性能极低
  2. 小心编译器和多处理器硬件
    • 就算实现对了,性能也极低 (何况很容易实现错)

是个不错的练习,但应该从这门课删除

  • (我们不是在讲这个算法;而是在告诉大家不要这么搞)

总结

我们得到了什么?

证明了 Peterson 算法在无编译优化、单处理器上的正确性。 (我们的第一个 non-trivial 并发程序的理解和证明)


在一个简化的程序执行模型上探索了程序的行为

  • “model checking”
    • 把程序的正确性转换为了图问题
    • R. Jhala and R. Majumdar. Software model checking. ACM Computing Surveys, 41(4), 2009.

总结

本次课内容与目标

  • 用状态机理解程序 (Tower of Hanoi)
  • 用状态机模型理解并发程序 (Peterson's Algorithm)

Take-away message

  • 程序 = 状态机 = 有向图
    • 这门课用到最重要的工具