Rust 共享状态并发

Mutex/RwLock 与 Arc 组合实现共享可变状态;锁毒化、粒度与死锁风险。

#type / concept #status / growing #tech / dev #resource / rust

[!info] 关联笔记

Rust 共享状态并发

这个概念为什么出现

有时多线程必须共享可变状态(计数器、缓存)。
Rust 用 Mutex<T>/RwLock<T> 保护数据,用 Arc 共享锁本身。

[!abstract] 一句话理解 Arc<Mutex<T>> 让多线程共享同一把锁与数据;只有持有 guard 时才能访问 T,把互斥编码进类型。

最小可运行示例

场景:限流计数器——多线程递增通过数

网关工作线程并发递增“已放行请求”计数。

use std::sync::{Arc, Mutex};
use std::thread;

// 业务意图:并发安全递增计数器。
// 教学点:Arc 共享;lock 获取 guard;自动 unlock(Drop)。

fn main() {
    let counter = Arc::new(Mutex::new(0u64));
    let mut handles = vec![];
    for _ in 0..8 {
        let counter = Arc::clone(&counter);
        handles.push(thread::spawn(move || {
            let mut guard = counter.lock().unwrap();
            *guard += 1;
        }));
    }
    for h in handles { h.join().unwrap(); }
    println!("allowed={}", *counter.lock().unwrap());
}

建议运行:cargo run

期望输出:

allowed=8

结合场景再看三个关注点

  1. guard 离开作用域解锁(RAII)
  2. 锁粒度:只包最小临界区
  3. poison:持锁 panic 后 lock 返回 Err

核心概念与准确模型

原语场景
Mutex独占读写
RwLock多读或一写
Condvar等待条件
Barrier阶段同步

lock 返回 LockResult<MutexGuard<T>>

设计动机

  • 数据与锁绑定,避免未加锁访问
  • 与 Send/Sync 协作
  • Drop 防忘记解锁

边界与误区

  • 死锁:锁顺序不一致
  • 临界区太大损吞吐
  • async 代码误用 std Mutex 长时间持有

[!warning] 常见误区:先 channel 能解决还硬上全局大锁 优先缩小共享面。

工程实践

  1. 优先消息传递,共享状态次之
  2. 固定加锁顺序
  3. 处理 poison 或使用更稳健策略
  4. 指标监控锁等待

本节总结

  • Arc+Mutex 共享可变
  • RAII 解锁
  • 粒度与死锁是工程问题

自测题

  1. 为什么需要 Arc 包 Mutex?
  2. RwLock 读多写少的收益?
参考答案
  1. Mutex 要共享到多线程需要共享所有权。
  2. 并发只读不互斥阻塞彼此。

延伸阅读与资料来源

资料类型支撑内容
The Book — Shared State官方书Mutex
std::sync::Mutex标准库API
创建于 2026/7/15 更新于 2026/7/15