Course contentsShow
← Rust
Lesson 182 of 1,9102. The Ownership ModelFree lesson

Memory Safety for Parallel Iteration

Partition slices into distinct mutable chunks for safe parallel processing.

Memory Safety for Parallel Iteration

In this lesson, you will learn how to safely divide a single collection into distinct, non-overlapping mutable chunks so that multiple threads can process your data simultaneously without risking memory corruption.

The Conflict of Parallel Mutation

In Rust, the borrow checker enforces a strict rule: you can have either many immutable references OR exactly one mutable reference to a piece of data. When you want to modify different parts of a slice in parallel, you might think you need a lock. However, locking every element would destroy your performance.

The secret to safe parallel iteration is partitioning. By mathematically splitting a single &mut [T] into several smaller &mut [T] slices, each covering a unique range of indices, you satisfy the compiler's safety requirements. Because each thread owns a distinct "slice" of the memory, the compiler knows for certain that no two threads can touch the same index, eliminating the need for expensive runtime locks.

Splitting Slices Safely

Rust provides built-in methods designed specifically for this purpose, such as split_at_mut. This method takes an index and returns two separate mutable slices that effectively carve your data into isolated "work zones."

let mut data = [1, 2, 3, 4];

// Divide the slice into two distinct mutable parts
let (left, right) = data.split_at_mut(2);

// Now 'left' ([1, 2]) and 'right' ([3, 4]) are separate mutable references.
// We can safely hand these to different threads to process concurrently!
left[0] += 10;
right[0] += 20;

When you use this pattern, you are creating a "provenance" trail. Because the compiler can track that left and right originated from a safe split of the original data, it allows you to mutate both simultaneously. As long as the partitions are distinct, memory safety is guaranteed at compile time, and your CPU can process the data in parallel without any risk of data races.

Key Takeaway: By partitioning a mutable slice into non-overlapping sub-slices, you provide the borrow checker with proof that your parallel threads are isolated, enabling safe, high-performance concurrency without the overhead of locks.