【中间件】brpc_基础_butex.h
butex.h 学习笔记
源码
1 概述
butex.h
提供了一种用户态同步原语 butex(类似 Linux 的 futex
),专为 bthread
设计,用于高效协调线程的阻塞与唤醒。其核心是通过原子操作结合等待队列管理,减少内核态切换开销,适用于高并发场景。
2 核心功能模块
2.1 基本操作
-
创建与销毁:
butex_create()
: 创建 32 位 butex 对象,返回指针(非跨进程)。butex_create_checked<T>()
: 类型安全的创建(需sizeof(T) == sizeof(int)
)。butex_destroy()
: 销毁 butex,释放资源。
-
等待机制:
butex_wait()
: 原子等待 butex 值等于expected_value
,支持超时(绝对时间abstime
)和队列插入位置控制(prepend
决定头或尾)。
-
唤醒机制:
- 单次唤醒:
butex_wake()
唤醒至多 1 个线程。 - 批量唤醒:
butex_wake_n(n)
唤醒最多n
个线程(n=0
唤醒全部)。 - 排除唤醒:
butex_wake_except()
唤醒除指定线程外的所有等待者。 - 队列转移:
butex_requeue()
唤醒一个线程,其余迁移到另一 butex。
- 单次唤醒:
2.2 关键设计特点
-
轻量高效:
- 用户态实现,避免内核切换。
MIN_SLEEP_US=2
:短于 2μs 的休眠直接返回ETIMEDOUT
,减少无意义等待。
-
灵活唤醒策略:
- 支持精确控制唤醒数量、排除特定线程、转移等待队列,满足复杂同步需求(如锁优化、条件变量实现)。
-
时间处理:
butex_wait
使用绝对时间(abstime
),与futex
的相对时间不同,需调用方正确处理时间转换。
-
队列顺序控制:
prepend
参数允许将线程插入等待队列头部,影响唤醒顺序(如实现非公平锁)。
3 使用场景与示例
场景 1:实现互斥锁
- 加锁:检查 butex 值,若为 0(未锁定),原子设置为 1;否则调用
butex_wait
阻塞。 - 解锁:设置 butex 为 0,调用
butex_wake
唤醒一个等待线程。 - 优化:使用
butex_requeue
减少竞争,将等待线程迁移到另一队列。
场景 2:条件变量
- 等待条件:结合互斥锁,释放锁后调用
butex_wait
进入等待。 - 通知条件:条件满足时,通过
butex_wake_all
唤醒所有等待线程。
场景 3:任务取消
- 使用
butex_wake_except
唤醒除当前任务外的所有线程,避免自唤醒。
4 注意事项
-
资源管理:
- 必须成对调用
butex_create
和butex_destroy
,防止内存泄漏。 - 确保
butex_wait
前检查条件,避免虚假唤醒(类似pthread_cond_wait
)。
- 必须成对调用
-
时间处理:
- 传递
abstime
时需使用CLOCK_REALTIME
时间,正确计算绝对时间点。
- 传递
-
线程安全:
- butex 本身不保证线程安全,需结合原子操作或上层同步原语使用。
-
性能优化:
- 短时等待直接返回
ETIMEDOUT
,避免无意义调度。 nosignal
参数可能用于减少信号开销,需根据场景选择。
- 短时等待直接返回
5 函数对比与扩展
函数 | 功能 | 类比 futex |
---|---|---|
butex_wake | 唤醒 1 个线程 | FUTEX_WAKE (1) |
butex_wake_n | 唤醒最多 n 个线程 | FUTEX_WAKE (n) |
butex_requeue | 唤醒 1 个,转移其余到另一 butex | FUTEX_REQUEUE |
butex_wait | 带条件的等待(绝对超时) | FUTEX_WAIT_BITSET |
6 总结
butex
是 bthread
库中高效同步的核心机制,通过用户态原子操作与等待队列管理,为上层同步原语(如互斥锁、条件变量)提供基础。其设计注重灵活性与性能,适用于高并发、低延迟场景。开发者需合理选择唤醒策略、处理时间与资源,以充分发挥其优势。