Day 3:訊息傳遞(mpsc 通道)

學習目標

  • 用 mpsc::channel 建立通道
  • 在執行緒間傳遞訊息
  • 用 Receiver 迭代接收

今日重點

單一發送者

use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();   // tx: 發送端, rx: 接收端

    thread::spawn(move || {
        tx.send(String::from("hello")).unwrap();
        tx.send(String::from("from thread")).unwrap();
    });

    // 接收端可用迭代方式收到所有訊息
    for received in rx {
        println!("Got: {}", received);
    }
}

mpsc = **m**ulti-**p**roducer, **s**ingle-**c**onsumer。多個發送者、單一接收者。

多個發送者(clone tx)

let (tx, rx) = mpsc::channel();

for i in 0..5 {
    let tx_clone = tx.clone();
    thread::spawn(move || {
        tx_clone.send(format!("Message {}", i)).unwrap();
    });
}
drop(tx);   // 關閉原始發送端

// 所有 tx 都 drop 後,迭代才會結束
for received in rx {
    println!("Received: {}", received);
}

必須 clone 之後把**所有** tx(含原始)都 drop,接收端的 for 才會在收完後結束,否則會永遠 block 等待。

練習

use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    // 1. 一個執行緒依序發送 "a", "b", "c"
    thread::spawn(move || {
        for msg in ["a", "b", "c"] {
            tx.send(msg).unwrap();
        }
    });

    // 2. 主執行緒迭代接收
    for msg in rx {
        println!("{}", msg);
    }
}
3. 增加第二個發送端,clone tx,讓兩個執行緒同時發送。

自我檢查

  • 知道 mpsc 的全名
  • 會建立通道與 send / iter
  • 知道要 drop 所有發送端迭代才會結束
  • 理解訊息傳遞是安全並發的好方法

深入連結

  • The Book 第 16 章「Using Message Passing to Transfer Data Between Threads」