Message passing helps different parts of a program talk to each other safely without mixing up data.
When you want to send data between different parts of a program running at the same time.
When you want to avoid mistakes caused by sharing data directly.
When you want to organize your program so parts work independently but still communicate.
When you build programs that do many things at once, like a chat app or a game.
When you want to keep your program safe from crashes caused by data conflicts.
Syntax
Rust
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
// tx is the sender// rx is the receiver// Send a message
let _ = tx.send("Hello");
// Receive a message
let message = rx.recv().unwrap();
}
mpsc stands for multiple producer, single consumer.
You create a channel with mpsc::channel() which gives you a sender and a receiver.
Examples
Send and receive a number using the channel.
Rust
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
tx.send(5).unwrap();
let received = rx.recv().unwrap();
println!("Got: {}", received);
}
Send a message from a new thread to the main thread.
Rust
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send("Hi from thread").unwrap();
});
let message = rx.recv().unwrap();
println!("Message: {}", message);
}
You can clone the sender to have multiple senders.
Rust
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
let tx2 = tx.clone();
// Now two senders can send messages
}
Sample Program
This program creates a channel and a new thread. The thread sends three messages one by one. The main thread receives and prints each message.
Rust
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let messages = vec!["Hello", "from", "thread"];
for msg in messages {
tx.send(msg).unwrap();
}
});
for received in rx {
println!("Got: {}", received);
}
}
OutputSuccess
Important Notes
Sending messages moves ownership, so data is safely transferred.
Receiving blocks the program until a message arrives.
Cloning the sender lets many parts send messages to one receiver.
Summary
Message passing lets parts of a program send data safely without sharing memory.
Use mpsc::channel() to create a sender and receiver.
Senders use send(), receivers use recv() to get messages.
Practice
(1/5)
1. What is the main purpose of message passing in Rust?
easy
A. To share memory directly between threads
B. To speed up program execution by skipping safety checks
C. To safely send data between parts of a program without sharing memory
D. To write data to files asynchronously
Solution
Step 1: Understand message passing concept
Message passing allows different parts of a program to communicate by sending data safely without sharing memory directly.
Step 2: Compare options with concept
Only To safely send data between parts of a program without sharing memory correctly describes this safe data transfer without shared memory. Other options describe unrelated or incorrect behaviors.
Final Answer:
To safely send data between parts of a program without sharing memory -> Option C
Quick Check:
Message passing = safe data transfer without shared memory [OK]
Hint: Message passing means no shared memory, just safe data send [OK]
Common Mistakes:
Thinking message passing shares memory directly
Confusing message passing with file I/O
Assuming message passing skips safety checks
2. Which of the following is the correct way to create a channel for message passing in Rust?
easy
A. let (tx, rx) = mpsc::channel();
B. let (tx, rx) = channel::mpsc();
C. let (tx, rx) = mpsc.channel();
D. let (tx, rx) = mpsc_channel();
Solution
Step 1: Recall Rust syntax for creating channels
Rust's standard library uses mpsc::channel() function to create a sender and receiver pair.
Step 2: Check each option's syntax
Only let (tx, rx) = mpsc::channel(); uses the correct syntax: mpsc::channel(). Others have wrong function names or syntax errors.
Hint: Use mpsc::channel() to get sender and receiver [OK]
Common Mistakes:
Using dot instead of double colon (::)
Swapping function and module names
Using incorrect function names like mpsc_channel
3. What will be the output of this Rust code?
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(10).unwrap();
});
let received = rx.recv().unwrap();
println!("{}", received);
}
medium
A. Compilation error
B. Thread panicked
C. No output
D. 10
Solution
Step 1: Understand the code flow
A channel is created, a thread sends the value 10 through the sender, and the main thread receives it and prints it.
Step 2: Predict the output
The receiver gets 10 and prints it, so the output is "10".
Final Answer:
10 -> Option D
Quick Check:
Sent 10, received 10, printed 10 [OK]
Hint: Sender sends 10, receiver prints 10 [OK]
Common Mistakes:
Thinking thread panics due to move keyword
Assuming recv() blocks forever
Expecting compilation error due to unwrap
4. Identify the error in this Rust code using message passing:
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(|| {
tx.send(5).unwrap();
});
println!("{}", rx.recv().unwrap());
}
medium
A. tx is moved into the thread but not declared as move
B. rx cannot receive messages from another thread
C. send() returns a Result that is not handled
D. channel() returns a tuple, not two variables
Solution
Step 1: Analyze thread closure and tx usage
The closure uses tx but does not declare move, so tx cannot be moved into the thread.
Step 2: Understand Rust's ownership rules
Without move keyword, tx cannot be captured by the thread closure, causing a compile error.
Final Answer:
tx is moved into the thread but not declared as move -> Option A
Quick Check:
Missing move keyword for tx in thread closure = tx is moved into the thread but not declared as move [OK]
Hint: Use move keyword to transfer ownership into thread [OK]
Common Mistakes:
Ignoring ownership rules for thread closures
Thinking recv() can't get messages from other threads
Assuming send() Result can be ignored without unwrap
5. You want to send multiple messages from one thread to another using Rust's mpsc channel. Which approach correctly allows sending multiple messages without cloning the sender each time?
hard
A. Create a new channel for each message
B. Use a single sender and send messages sequentially before dropping it
C. Clone the sender once and use the clone to send all messages
D. Use a receiver to send messages back to the sender
Solution
Step 1: Understand sender usage in mpsc
A single sender can send multiple messages sequentially before it is dropped; cloning is only needed if multiple threads send concurrently.
Step 2: Evaluate options for sending multiple messages
Use a single sender and send messages sequentially before dropping it correctly uses one sender to send multiple messages. Clone the sender once and use the clone to send all messages clones unnecessarily. Create a new channel for each message creates many channels, which is inefficient. Use a receiver to send messages back to the sender misuses receiver as sender.
Final Answer:
Use a single sender and send messages sequentially before dropping it -> Option B
Quick Check:
Single sender can send multiple messages sequentially [OK]
Hint: One sender can send many messages sequentially without cloning [OK]
Common Mistakes:
Cloning sender unnecessarily for single-threaded sends
Creating multiple channels instead of reusing one
Confusing receiver with sender roles
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.