信号量:应用

信号量:应用

2024 南京大学《操作系统:设计与实现》
信号量:应用

信号量的两种典型应用

1. 实现一次临时的 happens-before: ABA \to B

  • AV(s)P(s)BA \to V(s) \to P(s) \to B
    • 这就是刚才的 “互斥锁实现同步”

2. 管理计数型资源

  • 游泳池里的人不能超过 nn
  • 停车场里的车不能超过 nn
  • 但可以有多个 “停车场”、“游泳池”
  • 我们也可以创造出车位
2024 南京大学《操作系统:设计与实现》
信号量:应用

例子:线程 join()

1. 形成 happens-before

  • worker: V(donet)V(\mathit{done}_t)
  • main: P(done1)P(done2)P(doneT)P(\mathit{done}_1) \to P(\mathit{done}_2) \ldots \to P(\mathit{done}_T)
  • 描述了一个 “计算图”

2. 使用计数型资源

  • worker: V(done)V(\mathit{done})
  • main: P(done)×TP(\mathit{done}) \times T
2024 南京大学《操作系统:设计与实现》
信号量:应用

例子:优雅地实现生产者-消费者

信号量设计思路

  • 考虑 “球”/“手环” (每一单位的 “资源”) 是什么
  • 生产者/消费者 = 把球从一个袋子里放到另一个袋子里
void produce() {
    P(&empty);
    printf("(");
    V(&fill);
}

void consume() {
    P(&fill);
    printf(")");
    V(&empty);
}
2024 南京大学《操作系统:设计与实现》
信号量:应用

例子:实现更复杂的同步

Fish

  • TaT_a: 死循环打印 <
  • TbT_b: 死循环打印 >
  • TcT_c: 死循环打印 _

同步这些线程

  • 保证打印出 <><_><>_ 的序列?
2024 南京大学《操作系统:设计与实现》
信号量:应用

信号量实现同步:问题分析

一个小困难

  • 假设刚打印完一条完整的鱼
    • <><_><>_
  • <> 都是可行的
    • 信号量似乎不太好表达 “二选一”

使用 happens-before

  • 为每个字符设置一个信号量
    • 例如,打印 < 的就 P(<)
  • 维护状态机,由上一个完成的线程决定 V 哪一种字符
2024 南京大学《操作系统:设计与实现》