条件编译策略
根据 multitasks 特性启用情况选择锁实现:
- 启用 multitasks:使用自定义的
Mutex - 未启用 multitasks:使用自旋锁(
kspin)
自定义 Mutex 实现基于 lock-api crate,提供统一的接口。
锁结构设计
pub struct RawMutex {
wq: WaitQueue, // 等待队列:存储被阻塞的任务
owner_id: AtomicU64, // 锁的持有者 ID(0 表示未锁定)
}核心方法实现
new():构造函数const INIT:RawMutex::new(),传递给lock-api作为锁初始化函数lock():阻塞式加锁,成功立即返回,失败时根据情况 panic 或重试try_lock():非阻塞加锁,失败处理交由下游代码unsafe unlock():使用swap()设置owner_id=0时获取旧值,校验持有者身份,最后调用notify_one(true)唤醒等待队列中的下一个任务is_locked():使用Relaxed内存序,仅需读取且无需顺序保证
安全使用模式
unlock() 无法在编译期保证持有者解锁,虽内置 panic 检查但属于运行时验证。因此不应直接调用 unlock(),而应利用 MutexGuard 的 Drop 机制:
{
let guard = mutex.lock(); // 返回 MutexGuard
// 使用 guard 访问数据
} // guard 离开作用域,自动调用 drop(),内部调用 unlock()内存序对比
| 内存序 | 中文名 | 保证 | 使用场景 | 开销 |
|---|---|---|---|---|
Acquire | 获取序 | 防止后续操作被重排到之前 | 加锁、读取共享数据 | 中等 |
Release | 释放序 | 防止之前操作被重排到之后 | 解锁、写入共享数据 | 中等 |
Relaxed | 宽松序 | 只保证原子性,不保证顺序 | 计数器、状态标志 | 最低 |
接口封装
使用类型别名包装 lock-api 提供的接口,简化使用。
没有评论