CodeToLive

Concurrency in Rust

Rust provides powerful tools for concurrent programming, including threads, channels, and asynchronous tasks.

Threads

Use the std::thread module to create and manage threads.


use std::thread;

fn main() {
  let handle = thread::spawn(|| {
    println!("Hello from a thread!");
  });

  handle.join().unwrap();
}
      

Mutex and Arc

Use Mutex and Arc to safely share data between threads.


use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
  let counter = Arc::new(Mutex::new(0));
  let mut handles = vec![];

  for _ in 0..10 {
    let counter = Arc::clone(&counter);
    let handle = thread::spawn(move || {
      let mut num = counter.lock().unwrap();
      *num += 1;
    });
    handles.push(handle);
  }

  for handle in handles {
    handle.join().unwrap();
  }

  println!("Result: {}", *counter.lock().unwrap());
}
      

Channels

Use channels to communicate between threads.


use std::sync::mpsc;
use std::thread;

fn main() {
  let (sender, receiver) = mpsc::channel();

  thread::spawn(move || {
    sender.send("Hello from the thread!").unwrap();
  });

  let message = receiver.recv().unwrap();
  println!("Received: {}", message);
}
      

Thread Pools

Use thread pools to manage multiple threads efficiently.


use std::sync::mpsc;
use std::thread;

fn main() {
  let (sender, receiver) = mpsc::channel();

  for i in 0..4 {
    let sender = sender.clone();
    thread::spawn(move || {
      sender.send(i).unwrap();
    });
  }

  for _ in 0..4 {
    println!("Received: {}", receiver.recv().unwrap());
  }
}
      

Async/Await

Use the async and await keywords for asynchronous programming.


use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
  println!("Starting...");
  sleep(Duration::from_secs(2)).await;
  println!("Done!");
}
      

Async Channels

Use asynchronous channels with tokio for non-blocking communication.


use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
  let (mut sender, mut receiver) = mpsc::channel(32);

  tokio::spawn(async move {
    sender.send("Hello from async channel!").await.unwrap();
  });

  let message = receiver.recv().await.unwrap();
  println!("Received: {}", message);
}
      

Error Handling in Concurrency

Handle errors in concurrent Rust programs using Result and unwrap.


use std::thread;

fn main() {
  let handle = thread::spawn(|| {
    let result: Result<(), &str> = Err("Something went wrong!");
    result.unwrap();
  });

  if let Err(e) = handle.join() {
    println!("Thread panicked: {:?}", e);
  }
}
      

Interactive Code Examples

Try running these examples in your Rust environment to see how they work!


// Interactive Example
use std::thread;

fn main() {
  let handle = thread::spawn(|| {
    println!("Hello from a thread!");
  });

  handle.join().unwrap();
}
      

Practice Problems

Test your understanding with these practice problems:

  1. Write a Rust program to create two threads that increment a shared counter using Mutex.
  2. Write a Rust program to send multiple messages between threads using channels.
  3. Write a Rust program to simulate a task queue using a thread pool.
Next: Ownership and Borrowing in Rust