实现互斥:操作系统也来帮忙了!

实现互斥:操作系统也来帮忙了!

2025 南京大学《操作系统原理》
实现互斥:操作系统也来帮忙了!

性能的另一个维度:Scalability

系统随着需求或负载增加时,依然能够保持性能和稳定性,灵活扩展资源的能力。(另一个角度:在资源增长时,能维持或提升性能的能力)

center

Spinlock 已经可以算是 performance bug 了
2025 南京大学《操作系统原理》
实现互斥:操作系统也来帮忙了!

自旋锁的 Scalability 问题

性能问题 (1)

  • 除了获得锁的线程,其他处理器上的线程都在空转
    • “一核有难,八核围观”
    • 如果代码执行很久,不如把处理器让给其他线程

性能问题 (2)

  • 应用程序不能关中断……
    • 持有自旋锁的线程被切换
    • 导致 100% 的资源浪费
    • (如果应用程序能 “告诉” 操作系统就好了)
      • 你是不是想到了什么解决方法?
2025 南京大学《操作系统原理》
实现互斥:操作系统也来帮忙了!

线程自己解决不了,就让操作系统来帮忙

把锁的实现放到操作系统里就好啦

  • syscall(SYSCALL_acquire, &lk);
    • 试图获得 lk,但如果失败,就切换到其他线程
  • syscall(SYSCALL_release, &lk);
    • 释放 lk,如果有等待锁的线程就唤醒
  • 剩下的复杂工作都交给内核
    • 关中断 + 自旋
      • 自旋锁只用来保护操作系统中非常短的代码块
    • 成功获得锁 → 返回
    • 获得失败 → 设置线程为 “不可执行” 并切换
2025 南京大学《操作系统原理》
实现互斥:操作系统也来帮忙了!

pthread Mutex Lock

与自旋锁完全一致,而且性能足够好

pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);

pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);

编程的时候用这个就行啦!

  • 没有争抢的时候性能非常好
    • 甚至都不需要 trap 进操作系统内核
  • 更多线程争抢时也有相当好的 scalability
    • 这么神奇?
2025 南京大学《操作系统原理》
实现互斥:操作系统也来帮忙了!

Futex: Fast Userspace muTexes 🌶️

小孩子才做选择。操作系统当然是全都要啦!

  • 性能优化的最常见技巧:优化 fast path

Fast Path: 自旋一次

  • 一条原子指令,成功直接进入临界区

Slow Path: 自旋失败

  • 请求系统调用 futex_wait
  • 请操作系统帮我达到自旋的效果
    • (实际上并不真的自旋)
2025 南京大学《操作系统原理》
实现互斥:操作系统也来帮忙了!

Futex: Fast Userspace muTexes 🌶️

比你想象的复杂

  • 如果没有锁的争抢,Fast Path 不能调用 futex_wake
  • 自旋失败 → 调用 futex_wait → 线程睡眠
    • 如果刚开始系统调用,自旋锁被立即释放?
    • 如果任何时候都可能发生中断?

并发:水面下的冰山

2025 南京大学《操作系统原理》