“使用 Futex 的乐趣:为 funtex 在 C 中构建我自己的互斥锁”

主要观点:在 Linux 中实现优化锁需要操作系统帮助,用户态实现有局限,需探讨 C 语言中简单自旋锁及使用操作系统原语的更精细锁的实现。互斥锁(mutex)的基本思想是代码部分在同一时间仅被单个线程访问,关键在于实现“等待”部分。
关键信息:

  • 简单自旋锁实现:通过atomic_exchange判断锁是否可用,true表示已被占用需自旋等待,false则可获取锁,用lockunlock函数实现。测试代码中创建多个线程尝试获取锁并递增计数器,展示了自旋锁可能导致高 CPU 消耗的问题。
  • futex系统调用:用于更好地处理锁的“等待”部分,提供FUTEX_WAITFUTEX_WAKE操作,通过整数值控制线程睡眠和唤醒,介绍了futex的几种场景。
  • 基于futex的互斥锁实现:结构体使用 32 位整数,lock函数通过atomic_compare_exchange_weak尝试获取锁,unlock函数调用FUTEX_WAKE唤醒等待线程,还提到改进的futex锁避免不必要的系统调用。
  • 性能比较:自旋锁在某些情况下比futex锁更快,通过修改自旋锁代码使其更高效;在高争用场景下,改进后的futex锁性能更好,总耗时和 CPU 时间都更低。
    重要细节:
  • atomic_exchange返回locked的旧值,用于判断锁的状态。
  • futex操作时需注意条件判断和原子性,如调用FUTEX_WAIT前内核会先原子性检查条件,避免不必要的睡眠。
  • 改进的futex锁中,通过区分互斥锁的不同状态来处理等待和唤醒线程的逻辑,避免不必要的系统调用。
  • 文中还提到后续可探索的方向,如实现自旋和futex结合的锁、深入研究 Rust 和 Go 的互斥锁实现、考虑公平性和内存排序等。
    参考文献:提供了多个关于futex和锁相关的资料来源,包括系统调用手册页、研究论文、书籍章节和文章等。
阅读 16
0 条评论