liveBook · Manning

Mpsc

As explained in Learn Rust in a Month of Lunches

A channel is a communication abstraction with one or more sending endpoints and one receiving endpoint for transferring information between parts of a program.

An mpsc channel is a thread-safe communication path: many sending endpoints can send values to one receiving endpoint. Rust’s standard library keeps the Sender and Receiver connected even when they live in different functions, structs, or threads. section 12.5 section 12.5.1

A channel follows a small set of practical rules:

  • Create one with std::sync::mpsc::channel(), which returns a Sender and Receiver carrying the same generic type. section 12.5.1
  • Send values with Sender::send and receive them with Receiver::recv; both methods return Result values because either endpoint can be unavailable. section 12.5.2
  • Clone the Sender to give multiple threads their own sending endpoint, while keeping one Receiver to collect their messages. section 12.5.2
  • Treat recv as blocking: it waits for a value while a Sender remains alive, whereas try_recv checks immediately and may find nothing. section 12.5.2
  • Expect sending to fail after the Receiver is dropped, and expect receiving to return an error after all Senders are dropped and queued data is exhausted. section 12.5.2

Two senders, one receiver

Create a channel, clone its Sender, and move each sender into a separate thread. Each thread sends strings, while the receiver loops with while let Ok(message) = receiver.recv() and prints every message until the senders are gone. The messages arrive in the order the Receiver gets them, not as a separately coordinated sequence. section 12.5.2

use std::sync::mpsc::channel;
 
fn main() {
    let (sender, receiver) = channel();
    let sender_clone = sender.clone();
 
    std::thread::spawn(move || {
        sender.send("Send a &str this time").unwrap();             #1
        sender.send("Send a &str this time").unwrap();             #1
    });
 
    std::thread::spawn(move || {
        sender_clone.send("And here is another &str").unwrap();    #2
        sender_clone.send("And here is another &str").unwrap();    #2
    });
 
    while let Ok(res) = receiver.recv() {
        println!("{res}");
    }
}

Use the complete threaded example to inspect Sender cloning, move closures, repeated sends, and the receiving loop together. section 12.5.2

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains creation, generic typing, sending, receiving, blocking, cloning, endpoint drops, and common errors through focused examples.
Examples
Demonstrates integer transfer, cloned senders in two threads, blocking versus nonblocking reception, and closed-channel errors.
What it assumes
Assumes familiarity with multiple threads and introduces channel terminology, generic inference, endpoint ownership, and blocking behavior.
What you can do after
Build it from scratch with std::sync::mpsc::channel, cloned Sender values, send, recv, try_recv, and explicit error handling.
How it connects
Connects channels with threads, generic types, Result, ownership, and standard-library synchronization.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.