Rust 并发实战:用 Arc 与 Mutex 做线程安全的计数
test12026-09-224 次阅读
共享状态是并发的头号难题
Rust 的所有权系统把「数据竞争」挡在了编译期。当多个线程要修改同一份数据时,不能简单地共享一个可变变量,必须用 Arc 做原子引用计数、用 Mutex 做互斥锁,把可变访问串行化。下面用一个并发计数器说明完整写法。
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0u64));
let (tx, rx) = mpsc::channel::<u64>();
let mut handles = Vec::new();
for _ in 0..4 {
let counter = Arc::clone(&counter);
let tx = tx.clone();
handles.push(thread::spawn(move || {
for _ in 0..1000 {
let mut v = counter.lock().unwrap();
*v += 1;
}
tx.send(1).unwrap();
}));
}
drop(tx);
for h in handles {
h.join().unwrap();
}
for _ in rx {}
println!("final count = {}", *counter.lock().unwrap());
}
关键的三处设计
- Arc 让四个线程共享同一份 counter,clone 只是增加引用计数,开销极低。
- Mutex 保证同一时刻只有一个线程能 lock 并改写数值,把竞争变成串行。
- mpsc 通道用来等所有工作线程完成任务,主线程 join 之后才能安全读取结果。
锁竞争与替代方案
上面的例子最终会稳定打印 4000。但 Mutex 在高频写入时是性能瓶颈,每个线程都要抢同一把锁。如果只是一个计数器,改用 std::sync::atomic 的 AtomicU64 能去掉锁、性能更好;如果是多生产者多消费者队列,crossbeam-channel 比标准库 mpsc 更适合。
什么时候该上并发
- CPU 密集型任务(解析、计算)用能并行的工作线程能直接缩短耗时。
- IO 密集型任务优先用异步(Tokio),线程更适合需要真正并行计算的场景。
- 共享状态越少越好,能用通道传递所有权就别用锁,锁只留给必须共享的少量数据。
T
test1
文章作者
共享状态是并发的头号难题 Rust 的所有权系统把「数据竞争」挡在了编译期。当多个线程要修改同一份数据时,不能简单地共...
- 分类
- 技术
- 发布时间
- 2026-09-22
- 字数
- 约 1219 字
- 阅读
- 4 次
