本页目录

线程与同步原语

Rust 标准库的并发工具箱——Mutex/RwLock 提供共享可变访问,mpsc channel 在线程间传递消息(不共享内存),Condvar 做条件等待,atomics 和 Ordering 是无锁并发的根基。每个工具对应一种"线程间传递信息"的模式。

std::thread

let handle = std::thread::spawn(|| {
    println!("hello from another thread");
});
handle.join().unwrap();              // 等待线程结束

每个线程有独立栈(Linux 默认 2MB,可通过 Builder::stack_size 调整)。std::thread::spawn 的闭包必须 Send + 'static——线程可能比 spawner 活得久。

Mutex: 互斥锁

use std::sync::Mutex;
let m = Mutex::new(0);
* m.lock().unwrap() += 1;            // lock() 返回 MutexGuard
// MutexGuard drop → 自动 unlock (即使有 panic, unwinding 也会 drop)

MutexGuard<'_, T> 实现了 DerefMut(给你 &mut T)和 Drop(释放锁)。不需要手动 unlock()。如果持锁线程 panic,Mutex 被"poisoned"——后续 lock() 返回 Err(PoisonError),让你知道数据可能处于不一致状态。

RwLock: 读写锁

use std::sync::RwLock;
let lock = RwLock::new(42);
let r1 = lock.read().unwrap();       // 共享读锁
let r2 = lock.read().unwrap();       // 多个 reader 共存
// let w = lock.write().unwrap();    // WOULD BLOCK: readers active
drop(r1); drop(r2);                  // readers gone
let mut w = lock.write().unwrap();   // 现在可以写

RwLock 适用于读多写少。但要注意:如果 reader 持续不断,writer 可能饿死。std::sync::RwLock 不保证公平性(非 FIFO)——具体行为取决于操作系统调度器。

mpsc: 多生产者单消费者 channel

use std::sync::mpsc;
let (tx, rx) = mpsc::channel();
std::thread::spawn(move || { tx.send("hello").unwrap(); });
let msg = rx.recv().unwrap();        // 阻塞等待

recv() 阻塞当前线程直到有消息——这不是 async。async 场景用 tokio::sync::mpsc。当所有 tx 被 drop 时,rx.recv() 返回 Err(RecvError)——这点很重要:channel 的"关闭"是通过 sender 的 Drop 隐式传达的。

Condvar: 条件变量

use std::sync::{Arc, Mutex, Condvar};
let pair = Arc::new((Mutex::new(false), Condvar::new()));

// 等待线程:
let (lock, cvar) = &*pair;
let mut guard = lock.lock().unwrap();
while !*guard {
    guard = cvar.wait(guard).unwrap();  // 原子操作: 释放锁 + 阻塞
}

// 通知线程:
let (lock, cvar) = &*pair;
*lock.lock().unwrap() = true;
cvar.notify_one();

需要用 while 而非 if 检查条件——spurious wakeup 可能发生(操作系统可能在条件不满足时唤醒)。

Atomic 与 Ordering

use std::sync::atomic::{AtomicUsize, Ordering};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
COUNTER.fetch_add(1, Ordering::SeqCst);

Relaxed: 只保证原子性,不保证与周围内存操作的顺序——适用: 单纯计数,不需要与其他变量同步 Acquire/Release: 单向同步——Acquire 保证后续读看到 Release 之前的写。适用: 锁实现 SeqCst: 最强——全局顺序一致。适用: 默认选择,除非你知道为什么要更弱

参考

  • Rust Book: Chapter 16
  • Rustonomicon: Atomics, memory ordering
  • CppReference: memory_order (C++ 的定义也适用于 Rust 的原子模型)

Keywords: thread, Mutex, RwLock, mpsc, channel, Condvar, AtomicUsize, Ordering, SeqCst, Acquire, Release