条件编译策略

根据 multitasks 特性启用情况选择锁实现:

  • 启用 multitasks:使用自定义的 Mutex
  • 未启用 multitasks:使用自旋锁(kspin

自定义 Mutex 实现基于 lock-api crate,提供统一的接口。

锁结构设计

pub struct RawMutex {
    wq: WaitQueue,    // 等待队列:存储被阻塞的任务
    owner_id: AtomicU64, // 锁的持有者 ID(0 表示未锁定)
}

核心方法实现

  • new():构造函数
  • const INITRawMutex::new(),传递给 lock-api 作为锁初始化函数
  • lock():阻塞式加锁,成功立即返回,失败时根据情况 panic 或重试
  • try_lock():非阻塞加锁,失败处理交由下游代码
  • unsafe unlock():使用 swap() 设置 owner_id=0 时获取旧值,校验持有者身份,最后调用 notify_one(true) 唤醒等待队列中的下一个任务
  • is_locked():使用 Relaxed 内存序,仅需读取且无需顺序保证

安全使用模式

unlock() 无法在编译期保证持有者解锁,虽内置 panic 检查但属于运行时验证。因此不应直接调用 unlock(),而应利用 MutexGuardDrop 机制:

{
    let guard = mutex.lock(); // 返回 MutexGuard
    // 使用 guard 访问数据
} // guard 离开作用域,自动调用 drop(),内部调用 unlock()

内存序对比

内存序中文名保证使用场景开销
Acquire获取序防止后续操作被重排到之前加锁、读取共享数据中等
Release释放序防止之前操作被重排到之后解锁、写入共享数据中等
Relaxed宽松序只保证原子性,不保证顺序计数器、状态标志最低

接口封装

使用类型别名包装 lock-api 提供的接口,简化使用。