It’s time to explore the complex but powerful subject of concurrency in Rust. Concurrency is about structuring your program as independent tasks that can be executed in parallel, and Rust makes it a first-class citizen. Rust’s ownership model and strict compiler are its greatest strengths here, as they prevent entire classes of common concurrency bugs, like data races, at compile time.
Table of Contents
💻 Concurrency vs. Parallelism
It’s a common misconception that concurrency and parallelism are the same thing. They are related, but distinct concepts:
- Concurrency is about the composition of independently executing tasks. It’s a way to structure your program to handle many things at once.
- Parallelism is the simultaneous execution of multiple tasks. This is what happens when a concurrent program runs on a multi-core processor.
The goal of concurrency is to create a good structure; parallelism is a runtime benefit you get from that structure.
💻 Spawning Threads
A new thread can be spawned using the thread::spawn
function. This function takes a closure (an anonymous function) that contains the code the new thread will execute.
use std::thread;
fn main() {
let my_array = [1, 2, 3, 4, 5];
let join_handle = thread::spawn(move || {
println!("The array is {:?}", my_array);
});
// Wait for the thread to finish
join_handle.join().unwrap();
}
The move
keyword before the closure is crucial. It tells Rust to move ownership of any captured variables (like my_array
) into the new thread. The join_handle
returned by `spawn` allows the main thread to wait for the child thread to complete by calling the .join()
method.
💻 Sharing Data with `Arc` and `Mutex`
The biggest challenge in concurrency is safely sharing data between threads. Rust provides two main tools for this:
Arc
(Atomically Reference Counted): This is a smart pointer that allows multiple threads to have read-only ownership of the same data. It counts how many references exist and cleans up the data when the last reference is dropped.Mutex
(Mutual Exclusion): This provides interior mutability. A Mutex ensures that only one thread can access the data it protects at any given time. A thread must acquire a ‘lock’ on the mutex before it can read or write the data, preventing data races.
By combining these two—wrapping a Mutex
in an Arc
—you can safely share and mutate data across many threads.
More Topics
- Python Project Guide: NumPy & SciPy: For Science!
- Python Project Guide: Times, Dates & Numbers
- Python Project Guide: Making Scripts
- Python Project Guide: Build an FTP Client & Server
- Python Project Guide: Using Functions in Python 3
- Python Project Guide: How to Get Started with Python 3
- Coding Concepts Explained: Avoid Common Coding Mistakes