应用程序和互斥锁

应用程序和互斥锁

2024 南京大学《操作系统:设计与实现》
应用程序和互斥锁

应用程序自旋的后果

性能问题 (1)

  • 除了进入临界区的线程,其他处理器上的线程都在空转
    • 争抢锁的处理器越多,利用率越低
    • 如果临界区较长,不如把处理器让给其他线程

性能问题 (2)

  • 应用程序不能关中断……
    • 持有自旋锁的线程被切换
    • 导致 100% 的资源浪费
    • (如果应用程序能 “告诉” 操作系统就好了)
2024 南京大学《操作系统:设计与实现》
应用程序和互斥锁

应用程序:实现互斥

思路:“拟人”

  • 作业那么多,与其干等 Online Judge 发布,不如把自己 (CPU) 让给其他作业 (线程) 执行?

如何 “让”?

  • 只有一种特殊的指令能做到:syscall
  • 把锁的实现放到操作系统里就好啦
    • syscall(SYSCALL_lock, &lk);
      • 试图获得 lk,但如果失败,就切换到其他线程
    • syscall(SYSCALL_unlock, &lk);
      • 释放 lk,如果有等待锁的线程就唤醒
2024 南京大学《操作系统:设计与实现》
应用程序和互斥锁

pthread Mutex Lock

一个足够高性能的实现

  • 具有相当不错的 scalability
  • 更多线程争抢时也没有极为显著的性能下降

使用方法:与自旋锁完全一致

pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);

pthread_mutex_lock(&lock);
pthread_mutex_unlock(&lock);
2024 南京大学《操作系统:设计与实现》
应用程序和互斥锁

Futex: Fast Userspace muTexes 🌶️

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

  • 性能优化的最常见技巧:考虑平均而不是极端情况
    • RCU 就用了这个思想!

Fast Path: 自旋一次

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

Slow Path: 自旋失败

  • 请求系统调用 futex_wait
  • 请操作系统帮我达到自旋的效果
    • (实际上并不真的自旋)
2024 南京大学《操作系统:设计与实现》
应用程序和互斥锁

Futex: Fast Userspace muTexes 🌶️

比你想象的复杂

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

并发:水面下的冰山

2024 南京大学《操作系统:设计与实现》