---
title: 线程与同步原语
url: https://doc.liz6.com/rust/06-concurrency-and-asynchrony/04-threads-and-synchronization-primitives
locale: zh
area: rust
tags:
- rust
- 并发与异步
date: 2026-06-30
modified: 2026-06-30
description: Rust 标准库的并发工具箱——Mutex/RwLock 提供共享可变访问,mpsc channel 在线程间传递消息(不共享内存),Condvar 做条件等待,atomics 和 Ordering 是无锁并发的根基。每个工具对应一种"线程间传递信息"的模式。
---

# 线程与同步原语

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

## std::thread

```rust
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<T>: 互斥锁

```rust
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<T>: 读写锁

```rust
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

```rust
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: 条件变量

```rust
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

```rust
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*
