Day 6:Arc、Mutex 與並發設計

學習目標

  • 深入 Arc / Mutex 的組合
  • 比較「訊息傳遞 vs 共享狀態」
  • 理解 Send / Sync trait

今日重點

訊息傳遞 vs 共享狀態

訊息傳遞 共享狀態(Mutex)
推薦度 較推薦(Go 口號:don't share, pass message) 需要時用
心智負擔 低,資料靠通道傳 高,要小心鎖
死鎖風險
適合 工作分派、事件流 共享計數器、快取

Rust 兩者都有,掌握取捨是重點:優先訊息傳遞;需要緊密共享才 Mutex。

Send / Sync

  • Send:型別可以安全地**轉移所有權**到另一執行緒
  • Sync:型別可以安全地**被多執行緒同時引用**
  • Mutex<T> 是 Sync;Rc<T> 不是(Send/Sync 都是自動推導,除非含 unsafe)

Arc> 範例:共享取得訊息的 worker

use std::sync::{Arc, Mutex, mpsc};
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();
    let rx = Arc::new(Mutex::new(rx));   // 多執行緒共享一個接收端

    let mut handles = vec![];
    for id in 0..4 {
        let rx = Arc::clone(&rx);
        handles.push(thread::spawn(move || {
            loop {
                let job = rx.lock().unwrap().recv();
                match job {
                    Ok(msg) => println!("worker {}: {}", id, msg),
                    Err(_) => break,   // 通道關閉
                }
            }
        }));
    }

    for i in 0..8 { tx.send(format!("job {}", i)).unwrap(); }
    drop(tx);
    for h in handles { h.join().unwrap(); }
}

練習

  1. 跑上面的 worker 範例,觀察輸出與結束。
  2. 想想為什麼要用 Arc<Mutex<Receiver>> 而不是直接 clone rx。
  3. 用 dotenv 小題練習:寫一個「無死鎖」的好習慣(lock 的生命週期縮越短越好)。

自我檢查

  • 能用 Arc> 共享資料
  • 能比較訊息傳遞 vs 共享狀態
  • 知道 Send / Sync 的基本意義
  • 能設計簡單的多執行緒 worker

深入連結

  • The Book 第 16 章「Extensible Concurrency with the Sync and Send Traits」