One way threads coordinate is by passing messages instead of sharing memory. Rust's standard channel — mpsc — lets one thread send values to another, with ownership transferring along the way.
mpsc: multiple producer, single consumer
mpsc::channel() returns a (Sender, Receiver) pair. Threads holding a Sender call .send(value); the thread holding the Receiver calls .recv() (blocking) or iterates it. 'mpsc' = many senders, one receiver: you can clone the Sender to feed one receiver from several threads.
Sending transfers ownership
When you send a value, ownership moves into the channel and then to the receiver — the sender can't use it afterward. This is the same move semantics again, and it's why channels are race-free: a value is only ever owned by one side at a time. No shared mutable state means no lock and no data race.
Channels vs shared state
Two valid styles: message passing (channels, this lesson) and shared state (Arc<Mutex>, next lesson). Channels suit pipelines and producer/consumer setups — data flows one way. Shared state suits many threads reading and updating one structure. Real programs mix both; knowing which fits a problem is the skill.