281. mpsc::channel — Send Results Back Instead of Fighting Over a Mutex
Threads that only produce values don’t need shared state. A channel turns “everyone locks the accumulator” into “everyone mails in their answer.”
This morning’s bite 280 collected thread results through a Mutex, then peeled it off with into_inner. That works — but every worker contends for the same lock, and the value only exists to be fought over:
| |
With std::sync::mpsc, each worker gets its own Sender and the results flow one way:
| |
No lock, no poisoning, no unwrap on contention that can’t happen. Receiver implements Iterator, so collecting results is just rx.iter() — it yields each value as it arrives and ends when every Sender is gone.
That last part is the classic trap: the original tx counts too. Each worker got a clone, but the one you cloned from is still alive in the parent — if you don’t drop(tx), the channel never closes and rx.iter() blocks forever after the last worker exits. Symptom: all threads finished, program hangs.
mpsc is multi-producer, single-consumer: clone Sender freely, but there’s exactly one Receiver — which is why receiving needs no lock at all. Sends are non-blocking and buffered; if you want backpressure, mpsc::sync_channel(n) blocks senders once n messages are queued.
Mutexes are for threads that share data. When they only hand data back, give them a channel.
In std since Rust 1.0.