Sharing data through channels
An alternative approach to sharing data between threads, is to pass messages between threads using so-called: channels. By employing channels, each thread owns its own data, and the messages are synchronized in a thread-safe manner. Let's re-write our example using channels.
use tokio::join; use tokio::spawn; use tokio::sync::mpsc; #[derive(Debug)] struct User { id: String, } async fn lookup_user(id: &str, mut user_chan: mpsc::Sender<User>) { user_chan .send(User { id: id.to_string() }) .await .expect("can not send user on channel"); } #[tokio::main] async fn main() { let (tx, mut rx) = mpsc::channel(100); let mut users = vec![]; spawn(async move { join! { lookup_user("bob", tx.clone()), lookup_user("tom", tx), } }); while let Some(user) = rx.recv().await { println!("received: {user:?}"); users.push(user); } println!("Users: {users:?}"); }
As you can see, the users list does not need to be wrapped in a Mutex. This is because the main thread is the
only thread that is manipulating the users Vec. The lookup_user() function is returning the User through the
Sender half of the mpsc::channel. The data on the channel is automatically synchronized between threads.
mpsc stands for 'multi-producer, single-consumer' and supports sending many values from many producers to a single consumer. See Module tokio::sync for other channel types.
The channel constructor returns a tuple: tx and rx. These represent the Sender and Receiver halves of the
channel.
Only the Sender half can be cloned, hence the multi-producer term.
Notice that we are using the
join!macro from thetokiocrate toawaitbothlookup_usertasks.
If at all possible, prefer channels above sharing data between threads. It saves you from performance bottlenecks, where
threads are waiting on a Mutex lock. Channels, like the above, are buffered such that (up to a certain point) threads
can continue to send data without a delay.
Exercises
Now that you've learned about asynchronous programming with tokio, it's time to put your knowledge to the test.
Check out the corresponding exercise in the Exercises section. See you next time!