并发模型深度解析

本章目标: 深入理解 Rust 并发模型,掌握 Send/Sync、Arc/Mutex、Channel 和线程安全编程

学习时间: 5-7 天

前置知识: 完成 04-类型系统与Trait.md


Rust 并发的核心承诺

“无畏并发”(Fearless Concurrency) —— Rust 在编译期保证并发代码不会出现数据竞争。

Go 的并发:   运行时检测数据竞争 (race detector)
Rust 的并发: 编译期拒绝有数据竞争的代码

1. Send 和 Sync: 线程安全基石

Send Trait

// Send 表示类型可以安全地跨线程转移所有权
pub unsafe trait Send {}
 
// 自动实现 Send 的类型:
// i32, f64, bool, String, Vec<T> (T: Send), ...
 
// 不实现 Send 的类型:
// Rc<T> - 非原子引用计数
// *mut T - 裸指针
// MutexGuard (不能在另一个线程 drop)
use std::thread;
use std::rc::Rc;
use std::sync::Arc;
 
fn send_demo() {
    let s = String::from("hello");  // String: Send
    
    let handle = thread::spawn(move || {
        println!("{}", s);  // s 移动到新线程, OK
    });
    
    handle.join().unwrap();
    
    // Rc 不是 Send
    let rc = Rc::new(5);
    // thread::spawn(move || println!("{}", rc));  // 编译错误!
    
    // Arc 是 Send
    let arc = Arc::new(5);
    let arc2 = Arc::clone(&arc);
    thread::spawn(move || println!("{}", arc2)).join().unwrap();
}

Sync Trait

// Sync 表示类型可以被多个线程同时不可变访问
// T: Sync 等价于 &T: Send
pub unsafe trait Sync {}
 
// 不实现 Sync 的类型:
// Cell<T> - 没有同步保证的内部可变性
// RefCell<T> - 运行时借用检查, 非线程安全
// Rc<T>
use std::sync::{Arc, Mutex};
 
// Arc<T> 是 Send + Sync (如果 T: Send + Sync)
fn sync_demo() {
    let data = Arc::new(vec![1, 2, 3]);
    
    let mut handles = vec![];
    for i in 0..3 {
        let data = Arc::clone(&data);
        handles.push(thread::spawn(move || {
            // 多个线程同时读 (Sync)
            println!("Thread {}: data[{}] = {}", i, i, data[i]);
        }));
    }
    
    for h in handles {
        h.join().unwrap();
    }
}

Send + Sync 关系图

          T: Send?          T: Sync?
                |                |
         可跨线程移动        可跨线程共享读
                |                |
    Arc<T>: if T: Send+Sync → Send+Sync
    Mutex<T>: if T: Send → Send+Sync
    Rc<T>: Never Send, Never Sync
    Cell<T>: Send (if T: Send), Never Sync

2. 线程和共享状态

基础线程

use std::thread;
use std::time::Duration;
 
fn basic_threads() {
    let handle = thread::spawn(|| {
        for i in 0..5 {
            println!("spawned thread: {}", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
    
    for i in 0..5 {
        println!("main thread: {}", i);
        thread::sleep(Duration::from_millis(1));
    }
    
    handle.join().unwrap();  // 等待线程完成
}

Arc<Mutex>: 共享可变状态

use std::sync::{Arc, Mutex};
use std::thread;
 
fn shared_counter() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];
    
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });  // MutexGuard drop, 锁自动释放
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("Result: {}", *counter.lock().unwrap());  // 10
}

Mutex 内部工作原理

Arc<Mutex<T>> 内存布局:
┌──────────────────────────────────┐
│ Arc 控制块                        │
│   ref_count: AtomicUsize         │
├──────────────────────────────────┤
│ Mutex<T>                         │
│   locked: AtomicBool (或系统锁)  │
│   data: UnsafeCell<T>            │
└──────────────────────────────────┘

lock() 返回 MutexGuard:
- 实现 Deref/DerefMut → 访问内部数据
- 实现 Drop → 释放锁

死锁预防

use std::sync::{Arc, Mutex};
use std::thread;
 
// 死锁示例 (不要这样写!)
fn deadlock_example() {
    let lock1 = Arc::new(Mutex::new(1));
    let lock2 = Arc::new(Mutex::new(2));
    
    let l1 = Arc::clone(&lock1);
    let l2 = Arc::clone(&lock2);
    let t1 = thread::spawn(move || {
        let _a = l1.lock().unwrap();     // 获取 lock1
        thread::sleep(std::time::Duration::from_millis(1));
        let _b = l2.lock().unwrap();     // 等待 lock2 ← 可能死锁
    });
    
    let t2 = thread::spawn(move || {
        let _b = lock2.lock().unwrap();  // 获取 lock2
        thread::sleep(std::time::Duration::from_millis(1));
        let _a = lock1.lock().unwrap();  // 等待 lock1 ← 可能死锁
    });
    
    // 解决: 始终按相同顺序获取锁
}
 
// 正确做法: 锁排序
fn lock_ordering() {
    let lock1 = Arc::new(Mutex::new(1));
    let lock2 = Arc::new(Mutex::new(2));
    
    // 所有线程都先获取 lock1, 再获取 lock2
    fn get_both(l1: &Mutex<i32>, l2: &Mutex<i32>) -> (i32, i32) {
        let a = l1.lock().unwrap();
        let b = l2.lock().unwrap();
        (*a, *b)
    }
}

3. Channel: 消息传递

mpsc Channel (多生产者, 单消费者)

use std::sync::mpsc;
use std::thread;
 
fn basic_channel() {
    let (tx, rx) = mpsc::channel();
    
    thread::spawn(move || {
        let val = String::from("hello");
        tx.send(val).unwrap();
        // val 已被发送(移动), 不能再使用
        // println!("{}", val);  // 编译错误!
    });
    
    let received = rx.recv().unwrap();  // 阻塞等待消息
    println!("Got: {}", received);
}
 
// 多个生产者
fn multiple_producers() {
    let (tx, rx) = mpsc::channel();
    
    for i in 0..5 {
        let tx = tx.clone();  // 克隆发送端
        thread::spawn(move || {
            tx.send(i * i).unwrap();
        });
    }
    
    drop(tx);  // 关闭原始发送端
    
    // rx 会在所有 tx 都 drop 后关闭
    for received in rx {  // 迭代接收
        println!("Got: {}", received);
    }
}

Go Channel vs Rust Channel 对比

Go Channel:                 Rust mpsc Channel:
- 内置语法 (<-)             - 标准库 API
- 可以是有缓冲或无缓冲      - 有缓冲(sync_channel)和无缓冲
- 多生产者多消费者          - 多生产者单消费者(mpsc)
- select 语句              - 使用 crossbeam 的 select!
- GC 管理                  - 所有权管理

有缓冲 Channel

use std::sync::mpsc;
 
fn buffered_channel() {
    let (tx, rx) = mpsc::sync_channel(5);  // 缓冲区大小 5
    
    // 发送不会阻塞 (缓冲区未满)
    for i in 0..5 {
        tx.send(i).unwrap();
    }
    
    // 第 6 个会阻塞直到有空间
    // tx.send(5).unwrap();  // 会阻塞
    
    for v in rx.iter() {
        println!("{}", v);
    }
}

4. 并行计算: Rayon

// Rayon: 数据并行库
// cargo add rayon
 
use rayon::prelude::*;
 
fn parallel_computation() {
    let numbers: Vec<i64> = (1..=1_000_000).collect();
    
    // 顺序计算
    let sum_seq: i64 = numbers.iter().sum();
    
    // 并行计算 (几乎零代码改动!)
    let sum_par: i64 = numbers.par_iter().sum();
    
    assert_eq!(sum_seq, sum_par);
    
    // 并行 map + filter
    let result: Vec<i64> = numbers.par_iter()
        .filter(|&&x| x % 2 == 0)
        .map(|&x| x * x)
        .collect();
    
    println!("偶数平方的数量: {}", result.len());
}
 
// 并行排序
fn parallel_sort() {
    let mut data: Vec<i32> = (0..1_000_000).rev().collect();
    data.par_sort();  // 并行排序
    data.par_sort_by(|a, b| b.cmp(a));  // 并行逆序排序
}

5. 原子操作

use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
 
fn atomic_counter() {
    let counter = Arc::new(AtomicUsize::new(0));
    let mut handles = vec![];
    
    for _ in 0..1000 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            // 原子操作, 无需 Mutex
            counter.fetch_add(1, Ordering::Relaxed);
        });
        handles.push(handle);
    }
    
    for h in handles {
        h.join().unwrap();
    }
    
    println!("Counter: {}", counter.load(Ordering::Relaxed));  // 1000
}
 
// 原子标志
fn atomic_flag_demo() {
    let running = Arc::new(AtomicBool::new(true));
    let running_clone = Arc::clone(&running);
    
    let handle = thread::spawn(move || {
        let mut count = 0;
        while running_clone.load(Ordering::Acquire) {
            count += 1;
            if count % 1000000 == 0 {
                println!("Still running...");
            }
        }
        println!("Thread stopped after {} iterations", count);
    });
    
    thread::sleep(std::time::Duration::from_millis(10));
    running.store(false, Ordering::Release);  // 发送停止信号
    
    handle.join().unwrap();
}

内存序 (Memory Ordering)

// Ordering 从弱到强:
// Relaxed   - 只保证操作本身是原子的, 无顺序保证
// Acquire   - 读操作: 本次读之后的操作不会重排到读之前
// Release   - 写操作: 本次写之前的操作不会重排到写之后
// AcqRel    - 同时有 Acquire 和 Release 语义
// SeqCst    - 全序一致性, 最强但最慢
 
// 典型用法:
// 引用计数: Acquire/Release (Arc 内部使用)
// 标志位: AcqRel 或 SeqCst
// 简单计数器: Relaxed (不需要顺序保证)

6. 读写锁 (RwLock)

use std::sync::{Arc, RwLock};
use std::thread;
 
fn rwlock_demo() {
    let data = Arc::new(RwLock::new(vec![1, 2, 3]));
    let mut handles = vec![];
    
    // 多个读者
    for i in 0..5 {
        let data = Arc::clone(&data);
        handles.push(thread::spawn(move || {
            let read = data.read().unwrap();  // 获取读锁
            println!("Reader {}: {:?}", i, *read);
        }));
    }
    
    // 单个写者
    {
        let data = Arc::clone(&data);
        handles.push(thread::spawn(move || {
            let mut write = data.write().unwrap();  // 获取写锁
            write.push(4);
            println!("Writer appended 4");
        }));
    }
    
    for h in handles {
        h.join().unwrap();
    }
    
    println!("Final: {:?}", *data.read().unwrap());
}

7. 并发模式

工作池模式 (Worker Pool)

use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
 
type Job = Box<dyn FnOnce() + Send + 'static>;
 
pub struct ThreadPool {
    workers: Vec<thread::JoinHandle<()>>,
    sender: mpsc::Sender<Job>,
}
 
impl ThreadPool {
    pub fn new(size: usize) -> Self {
        let (sender, receiver) = mpsc::channel::<Job>();
        let receiver = Arc::new(Mutex::new(receiver));
        
        let workers = (0..size).map(|id| {
            let receiver = Arc::clone(&receiver);
            thread::spawn(move || {
                loop {
                    let job = receiver.lock().unwrap().recv();
                    match job {
                        Ok(job) => {
                            println!("Worker {} executing job", id);
                            job();
                        }
                        Err(_) => {
                            println!("Worker {} stopping", id);
                            break;
                        }
                    }
                }
            })
        }).collect();
        
        ThreadPool { workers, sender }
    }
    
    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        self.sender.send(Box::new(f)).unwrap();
    }
}
 
impl Drop for ThreadPool {
    fn drop(&mut self) {
        drop(self.sender.clone());  // 关闭 channel
        // workers 会在 channel 关闭后自然退出
    }
}
 
fn main() {
    let pool = ThreadPool::new(4);
    
    for i in 0..8 {
        pool.execute(move || {
            println!("Task {} running on thread {:?}", i, thread::current().id());
            thread::sleep(std::time::Duration::from_millis(100));
        });
    }
    
    thread::sleep(std::time::Duration::from_millis(1000));
}

Barrier: 屏障同步

use std::sync::{Arc, Barrier};
use std::thread;
 
fn barrier_demo() {
    let n = 5;
    let barrier = Arc::new(Barrier::new(n));
    let mut handles = vec![];
    
    for i in 0..n {
        let b = Arc::clone(&barrier);
        handles.push(thread::spawn(move || {
            println!("Thread {} starting phase 1", i);
            
            // 模拟不同速度的第一阶段
            thread::sleep(std::time::Duration::from_millis(i as u64 * 10));
            
            println!("Thread {} waiting at barrier", i);
            b.wait();  // 所有线程都到达才继续
            
            println!("Thread {} starting phase 2", i);
        }));
    }
    
    for h in handles {
        h.join().unwrap();
    }
}

8. 实战: 并行文件处理

use std::fs;
use std::io::{self, BufRead};
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::thread;
 
fn count_words_in_files(files: Vec<String>) -> std::collections::HashMap<String, usize> {
    let results = Arc::new(Mutex::new(std::collections::HashMap::new()));
    let mut handles = vec![];
    
    for file in files {
        let results = Arc::clone(&results);
        let handle = thread::spawn(move || {
            if let Ok(f) = fs::File::open(&file) {
                let reader = io::BufReader::new(f);
                let mut local_counts: std::collections::HashMap<String, usize> = 
                    std::collections::HashMap::new();
                
                for line in reader.lines().flatten() {
                    for word in line.split_whitespace() {
                        *local_counts.entry(word.to_lowercase()).or_insert(0) += 1;
                    }
                }
                
                // 合并到总结果
                let mut global = results.lock().unwrap();
                for (word, count) in local_counts {
                    *global.entry(word).or_insert(0) += count;
                }
            }
        });
        handles.push(handle);
    }
    
    for h in handles {
        h.join().unwrap();
    }
    
    Arc::try_unwrap(results)
        .expect("Still has references")
        .into_inner()
        .unwrap()
}

练习题

练习 1 (基础): Send/Sync 判断

以下哪些类型是 Send? 哪些是 Sync?

// 判断:
// a) Rc<i32>
// b) Arc<i32>
// c) Mutex<i32>
// d) Cell<i32>
// e) RefCell<i32>
// f) Arc<Mutex<i32>>
// g) *const i32

答案:

a) Rc<i32>:          不是 Send, 不是 Sync (引用计数非原子)
b) Arc<i32>:         是 Send, 是 Sync (原子引用计数)
c) Mutex<i32>:       是 Send, 是 Sync (提供同步保证)
d) Cell<i32>:        是 Send (如果 T: Send), 不是 Sync
e) RefCell<i32>:     是 Send (如果 T: Send), 不是 Sync
f) Arc<Mutex<i32>>:  是 Send, 是 Sync
g) *const i32:       不是 Send, 不是 Sync (裸指针)

练习 2 (基础): 并发计数器

实现一个线程安全的计数器:

use std::sync::{Arc, Mutex};
use std::thread;
 
fn main() {
    let counter = Arc::new(Mutex::new(HashMap::<String, usize>::new()));
    let mut handles = vec![];
    
    let words = vec!["apple", "banana", "apple", "cherry", "banana", "apple"];
    
    for word in words {
        let counter = Arc::clone(&counter);
        handles.push(thread::spawn(move || {
            let mut map = counter.lock().unwrap();
            *map.entry(word.to_string()).or_insert(0) += 1;
        }));
    }
    
    for h in handles {
        h.join().unwrap();
    }
    
    let result = counter.lock().unwrap();
    println!("{:?}", *result);
}

练习 3 (中等): Pipeline 模式

实现生产者-消费者 pipeline:

use std::sync::mpsc;
use std::thread;
 
fn pipeline() {
    // 阶段 1: 生成数据
    let (tx1, rx1) = mpsc::channel();
    thread::spawn(move || {
        for i in 0..10 {
            tx1.send(i).unwrap();
        }
    });
    
    // 阶段 2: 过滤偶数
    let (tx2, rx2) = mpsc::channel();
    thread::spawn(move || {
        for item in rx1 {
            if item % 2 == 0 {
                tx2.send(item).unwrap();
            }
        }
    });
    
    // 阶段 3: 平方
    let (tx3, rx3) = mpsc::channel();
    thread::spawn(move || {
        for item in rx2 {
            tx3.send(item * item).unwrap();
        }
    });
    
    // 收集结果
    let results: Vec<i32> = rx3.iter().collect();
    println!("{:?}", results);  // [0, 4, 16, 36, 64]
}

练习 4 (中等): 并行矩阵乘法

use std::sync::{Arc, Mutex};
use std::thread;
 
type Matrix = Vec<Vec<f64>>;
 
fn parallel_matmul(a: &Matrix, b: &Matrix, n_threads: usize) -> Matrix {
    let rows = a.len();
    let cols = b[0].len();
    let inner = b.len();
    
    let b = Arc::new(b.clone());
    let result = Arc::new(Mutex::new(vec![vec![0.0f64; cols]; rows]));
    
    let rows_per_thread = (rows + n_threads - 1) / n_threads;
    let mut handles = vec![];
    
    for t in 0..n_threads {
        let b = Arc::clone(&b);
        let result = Arc::clone(&result);
        let a_rows: Vec<Vec<f64>> = a[t * rows_per_thread..rows.min((t + 1) * rows_per_thread)]
            .to_vec();
        let row_offset = t * rows_per_thread;
        
        handles.push(thread::spawn(move || {
            let mut local: Vec<(usize, usize, f64)> = vec![];
            
            for (local_i, row) in a_rows.iter().enumerate() {
                let i = row_offset + local_i;
                for j in 0..cols {
                    let sum: f64 = (0..inner).map(|k| row[k] * b[k][j]).sum();
                    local.push((i, j, sum));
                }
            }
            
            let mut r = result.lock().unwrap();
            for (i, j, v) in local {
                r[i][j] = v;
            }
        }));
    }
    
    for h in handles {
        h.join().unwrap();
    }
    
    Arc::try_unwrap(result).unwrap().into_inner().unwrap()
}
 
fn main() {
    let a = vec![vec![1.0, 2.0], vec![3.0, 4.0]];
    let b = vec![vec![5.0, 6.0], vec![7.0, 8.0]];
    
    let c = parallel_matmul(&a, &b, 2);
    
    for row in &c {
        println!("{:?}", row);
    }
    // [19.0, 22.0]
    // [43.0, 50.0]
}

练习 5 (中等): 并发限速器

实现一个限制并发数的执行器:

use std::sync::{Arc, Mutex, Condvar};
use std::thread;
 
struct Semaphore {
    count: Mutex<usize>,
    cond: Condvar,
}
 
impl Semaphore {
    fn new(count: usize) -> Self {
        Semaphore {
            count: Mutex::new(count),
            cond: Condvar::new(),
        }
    }
    
    fn acquire(&self) {
        let mut count = self.count.lock().unwrap();
        while *count == 0 {
            count = self.cond.wait(count).unwrap();
        }
        *count -= 1;
    }
    
    fn release(&self) {
        *self.count.lock().unwrap() += 1;
        self.cond.notify_one();
    }
}
 
fn main() {
    let sem = Arc::new(Semaphore::new(3));  // 最多 3 个并发
    let mut handles = vec![];
    
    for i in 0..10 {
        let sem = Arc::clone(&sem);
        handles.push(thread::spawn(move || {
            sem.acquire();
            println!("Task {} running", i);
            thread::sleep(std::time::Duration::from_millis(100));
            println!("Task {} done", i);
            sem.release();
        }));
    }
    
    for h in handles {
        h.join().unwrap();
    }
}

练习 6 (挑战): 无锁队列 (使用原子操作)

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;
 
// 简单的单生产者单消费者无锁队列
struct SPSCQueue<T> {
    buffer: Vec<Option<T>>,
    head: AtomicUsize,
    tail: AtomicUsize,
    capacity: usize,
}
 
unsafe impl<T: Send> Send for SPSCQueue<T> {}
 
impl<T> SPSCQueue<T> {
    fn new(capacity: usize) -> Self {
        let mut buffer = Vec::with_capacity(capacity);
        for _ in 0..capacity {
            buffer.push(None);
        }
        SPSCQueue {
            buffer,
            head: AtomicUsize::new(0),
            tail: AtomicUsize::new(0),
            capacity,
        }
    }
    
    fn push(&self, item: T) -> bool {
        let tail = self.tail.load(Ordering::Relaxed);
        let next_tail = (tail + 1) % self.capacity;
        
        if next_tail == self.head.load(Ordering::Acquire) {
            return false;  // 队列满
        }
        
        unsafe { 
            let ptr = self.buffer.as_ptr().add(tail) as *mut Option<T>;
            ptr.write(Some(item));
        }
        
        self.tail.store(next_tail, Ordering::Release);
        true
    }
    
    fn pop(&self) -> Option<T> {
        let head = self.head.load(Ordering::Relaxed);
        
        if head == self.tail.load(Ordering::Acquire) {
            return None;  // 队列空
        }
        
        let item = unsafe {
            let ptr = self.buffer.as_ptr().add(head) as *mut Option<T>;
            ptr.replace(None)
        };
        
        self.head.store((head + 1) % self.capacity, Ordering::Release);
        item
    }
}

练习 7 (挑战): 并发下载器

实现一个简单的并发下载器(模拟):

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use std::collections::HashMap;
 
#[derive(Debug, Clone)]
enum DownloadStatus {
    Pending,
    Downloading(u8),  // 百分比
    Completed,
    Failed(String),
}
 
struct Downloader {
    tasks: Arc<Mutex<HashMap<String, DownloadStatus>>>,
    max_concurrent: usize,
}
 
impl Downloader {
    fn new(max_concurrent: usize) -> Self {
        Downloader {
            tasks: Arc::new(Mutex::new(HashMap::new())),
            max_concurrent,
        }
    }
    
    fn download(&self, urls: Vec<String>) {
        use std::sync::mpsc;
        let (tx, rx) = mpsc::channel::<String>();
        let semaphore = Arc::new((Mutex::new(0usize), std::sync::Condvar::new()));
        
        for url in &urls {
            self.tasks.lock().unwrap().insert(url.clone(), DownloadStatus::Pending);
        }
        
        let mut handles = vec![];
        
        for url in urls {
            let tasks = Arc::clone(&self.tasks);
            let tx = tx.clone();
            let sem = Arc::clone(&semaphore);
            let max = self.max_concurrent;
            
            let handle = thread::spawn(move || {
                // 限流
                {
                    let (lock, cvar) = &*sem;
                    let mut count = lock.lock().unwrap();
                    while *count >= max {
                        count = cvar.wait(count).unwrap();
                    }
                    *count += 1;
                }
                
                // 模拟下载
                for progress in (0..=100).step_by(20) {
                    tasks.lock().unwrap().insert(
                        url.clone(), 
                        DownloadStatus::Downloading(progress)
                    );
                    thread::sleep(Duration::from_millis(50));
                }
                
                tasks.lock().unwrap().insert(url.clone(), DownloadStatus::Completed);
                
                // 释放信号量
                {
                    let (lock, cvar) = &*sem;
                    *lock.lock().unwrap() -= 1;
                    cvar.notify_one();
                }
                
                tx.send(url).unwrap();
            });
            handles.push(handle);
        }
        
        drop(tx);
        
        for completed_url in rx {
            println!("Completed: {}", completed_url);
        }
        
        for h in handles {
            h.join().unwrap();
        }
    }
    
    fn status(&self) -> HashMap<String, DownloadStatus> {
        self.tasks.lock().unwrap().clone()
    }
}
 
fn main() {
    let downloader = Downloader::new(3); // 最多3个并发
    
    let urls = vec![
        "http://example.com/file1.zip".to_string(),
        "http://example.com/file2.zip".to_string(),
        "http://example.com/file3.zip".to_string(),
        "http://example.com/file4.zip".to_string(),
        "http://example.com/file5.zip".to_string(),
    ];
    
    downloader.download(urls);
    
    let status = downloader.status();
    println!("\nFinal status:");
    for (url, status) in &status {
        println!("{}: {:?}", url, status);
    }
}

练习 8 (综合): 生产者-消费者与背压

use std::sync::{Arc, Mutex, Condvar};
use std::sync::mpsc;
use std::thread;
 
// 带背压的有界 channel
struct BoundedChannel<T> {
    inner: Arc<(Mutex<BoundedChannelInner<T>>, Condvar, Condvar)>,
}
 
struct BoundedChannelInner<T> {
    buffer: std::collections::VecDeque<T>,
    capacity: usize,
    closed: bool,
}
 
impl<T: Send + 'static> BoundedChannel<T> {
    fn new(capacity: usize) -> (Self, Self) {
        let inner = Arc::new((
            Mutex::new(BoundedChannelInner {
                buffer: std::collections::VecDeque::new(),
                capacity,
                closed: false,
            }),
            Condvar::new(),  // not_full
            Condvar::new(),  // not_empty
        ));
        (BoundedChannel { inner: inner.clone() }, BoundedChannel { inner })
    }
    
    fn send(&self, item: T) -> bool {
        let (lock, not_full, not_empty) = &*self.inner;
        let mut guard = lock.lock().unwrap();
        
        while guard.buffer.len() >= guard.capacity && !guard.closed {
            guard = not_full.wait(guard).unwrap();
        }
        
        if guard.closed { return false; }
        
        guard.buffer.push_back(item);
        not_empty.notify_one();
        true
    }
    
    fn recv(&self) -> Option<T> {
        let (lock, not_full, not_empty) = &*self.inner;
        let mut guard = lock.lock().unwrap();
        
        while guard.buffer.is_empty() && !guard.closed {
            guard = not_empty.wait(guard).unwrap();
        }
        
        let item = guard.buffer.pop_front();
        if item.is_some() {
            not_full.notify_one();
        }
        item
    }
}

练习 9 (综合): 并发 KV 存储

use std::collections::HashMap;
use std::sync::{Arc, RwLock};
 
pub struct ConcurrentKV<K, V> {
    // 分片设计减少锁竞争
    shards: Vec<Arc<RwLock<HashMap<K, V>>>>,
    shard_count: usize,
}
 
impl<K, V> ConcurrentKV<K, V>
where
    K: std::hash::Hash + Eq + Clone,
    V: Clone,
{
    pub fn new(shard_count: usize) -> Self {
        let shards = (0..shard_count)
            .map(|_| Arc::new(RwLock::new(HashMap::new())))
            .collect();
        ConcurrentKV { shards, shard_count }
    }
    
    fn shard_index(&self, key: &K) -> usize {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};
        
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        hasher.finish() as usize % self.shard_count
    }
    
    pub fn insert(&self, key: K, value: V) {
        let idx = self.shard_index(&key);
        self.shards[idx].write().unwrap().insert(key, value);
    }
    
    pub fn get(&self, key: &K) -> Option<V> {
        let idx = self.shard_index(key);
        self.shards[idx].read().unwrap().get(key).cloned()
    }
    
    pub fn remove(&self, key: &K) -> Option<V> {
        let idx = self.shard_index(key);
        self.shards[idx].write().unwrap().remove(key)
    }
}
 
fn main() {
    let kv = Arc::new(ConcurrentKV::new(16));
    let mut handles = vec![];
    
    for i in 0..100 {
        let kv = Arc::clone(&kv);
        handles.push(std::thread::spawn(move || {
            kv.insert(format!("key{}", i), i * i);
        }));
    }
    
    for h in handles {
        h.join().unwrap();
    }
    
    println!("key42: {:?}", kv.get(&"key42".to_string()));
}

练习 10 (综合): 对比 Go 和 Rust 的并发

分析以下场景,用 Rust 实现 Go 的 sync.WaitGroup:

use std::sync::{Arc, Mutex, Condvar};
 
pub struct WaitGroup {
    inner: Arc<(Mutex<i32>, Condvar)>,
}
 
impl WaitGroup {
    pub fn new() -> Self {
        WaitGroup {
            inner: Arc::new((Mutex::new(0), Condvar::new())),
        }
    }
    
    pub fn add(&self, delta: i32) {
        let (lock, cond) = &*self.inner;
        let mut count = lock.lock().unwrap();
        *count += delta;
        if *count == 0 {
            cond.notify_all();
        }
    }
    
    pub fn done(&self) {
        self.add(-1);
    }
    
    pub fn wait(&self) {
        let (lock, cond) = &*self.inner;
        let mut count = lock.lock().unwrap();
        while *count > 0 {
            count = cond.wait(count).unwrap();
        }
    }
    
    pub fn clone(&self) -> Self {
        WaitGroup { inner: Arc::clone(&self.inner) }
    }
}
 
fn main() {
    let wg = WaitGroup::new();
    
    for i in 0..5 {
        let wg = wg.clone();
        wg.add(1);
        std::thread::spawn(move || {
            println!("Task {} running", i);
            std::thread::sleep(std::time::Duration::from_millis(100));
            println!("Task {} done", i);
            wg.done();
        });
    }
    
    wg.wait();
    println!("All tasks completed");
}

小结

概念要点
Send可跨线程转移所有权
Sync可跨线程共享引用
Arc原子引用计数, 多线程共享
Mutex互斥锁, 独占访问
RwLock读写锁, 多读单写
mpsc多生产者单消费者 channel
Rayon数据并行, par_iter

下一步

  • 完成本章所有练习题
  • 阅读 06-Unsafe与链表实现.md
  • 尝试用 rayon 优化一个计算密集任务

Rust 的并发安全由类型系统保证 —— 如果编译通过就说明没有数据竞争! 🦀