Course contentsShow
← Rust
Lesson 326 of 1,9103. Borrowing and ReferencesFree lesson

Ownership and Concurrency

Use ownership rules to eliminate data races in parallel programs.

In this lesson, you will learn how Rust’s ownership and borrowing rules act as a built-in "traffic controller" to prevent data races in your parallel programs.

The Problem: Data Races

A data race occurs when two or more threads access the same memory location simultaneously, at least one of those accesses is a write, and there is no synchronization mechanism to coordinate them. In many languages, avoiding these races requires manual locks and extreme vigilance. In Rust, the compiler forces you to handle memory access safely before you can even run your code.

Borrowing as a Concurrency Guard

You already know the core borrow rules:

  1. You can have any number of immutable references (&T) to a piece of data.
  2. You can have exactly one mutable reference (&mut T) to a piece of data.

When we introduce threads, these rules become your primary defense. If you try to share a variable across threads, the borrow checker verifies that you aren't violating these constraints. If a thread holds a mutable reference (&mut T) to a shared resource, the compiler ensures no other thread has access to that data at the same time. If you want to read data from multiple threads, you must use immutable references (&T), which are guaranteed by the compiler to never change while they are being read.

Consider this logic: If you have a &mut T in a thread, the borrow checker knows it is the exclusive owner of the ability to modify that data. Because the compiler prevents any other part of your program from having a reference to that same memory, it is logically impossible for a data race to occur.

// The compiler prevents this:
// Thread A: let data = &mut my_vec;
// Thread B: let view = &my_vec; // Error! Cannot borrow as immutable 
//                               // while already borrowed as mutable.

By adhering to the borrow checker, you move the complexity of synchronization from runtime debugging to compile-time verification. You don't have to "think" about avoiding races; if the code compiles, the ownership rules have already proven that your concurrent access pattern is memory-safe.

Key Takeaway: Rust’s ownership rules turn concurrency safety into a compile-time guarantee by ensuring that mutable access to shared data is always exclusive.