并发的硬件基础
原理
多线程并发在硬件层面由以下机制支撑:
缓存一致性协议(MESI):多核 CPU 通过总线嗅探维护 L1/L2 缓存一致性。Modified → Exclusive → Shared → Invalid 状态机确保所有核心看到一致的内存视图。
内存序(Memory Order):CPU 和编译器可能重排指令。x86 提供较强保证(Load-Load, Load-Store, Store-Store 不重排),Store-Load 可能重排。ARM 提供较弱保证——需要显式屏障。
原子操作:在 x86 上 LOCK 前缀锁住内存总线或缓存行,实现原子 RMW(read-modify-write)。std::sync::atomic 暴露了 Ordering::Relaxed/Acquire/Release/AcqRel/SeqCst。
Mutex 实现:std::sync::Mutex 底层用 futex(Linux)或 SRWLOCK(Windows)——先自旋锁(spinlock)尝试几次,失败则陷入内核等待。自旋锁适合临界区极短的场景。
Rust 的 Send / Sync trait 在编译期阻止数据竞争:Send = 可安全转移所有权到另一线程;Sync = 可安全地从另一线程通过引用访问。
语法
use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicI32, Ordering};
// 基础线程
let handle = thread::spawn(|| { println!("worker"); });
handle.join().unwrap();
// Arc + Mutex — 多线程共享可变状态
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let c = Arc::clone(&counter);
handles.push(thread::spawn(move || {
let mut n = c.lock().unwrap();
*n += 1;
}));
}
for h in handles { h.join().unwrap(); }
// 原子类型
let a = AtomicI32::new(0);
a.fetch_add(1, Ordering::SeqCst);
// mpsc 通道
use std::sync::mpsc;
let (tx, rx) = mpsc::channel();
thread::spawn(move || { tx.send(42).unwrap(); });
assert_eq!(rx.recv().unwrap(), 42);内存序层级
| Ordering | 保证 | 性能 |
|---|---|---|
Relaxed | 原子性,重排随意 | 最快 |
Acquire/Release | 成对同步,单方向屏障 | 中等 |
AcqRel | 双向屏障 | 慢 |
SeqCst | 全局顺序一致性 | 最慢 |
实践
力扣问题
力扣: 力扣线段树 — 单线程适用
AI 自检
- x86 的 TSO(Total Store Order)内存模型与 ARM 的弱内存模型的区别?
Mutex<T>和RwLock<T>的性能差异?读多写少的场景如何选择?