【中间件】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 库中高效同步的核心机制,通过用户态原子操作与等待队列管理,为上层同步原语(如互斥锁、条件变量)提供基础。其设计注重灵活性与性能,适用于高并发、低延迟场景。开发者需合理选择唤醒策略、处理时间与资源,以充分发挥其优势。
