Course contentsShow
← Rust
Lesson 460 of 1,9104. Lifetimes and Advanced OwnershipFree lesson

Inter-thread Data Transfer

Transfer ownership of data between threads efficiently using channels and mutexes.

In this lesson, you will learn how to safely and efficiently move ownership of data across thread boundaries using Rust's concurrency primitives.

The Ownership Principle in Threads

In Rust, threads are independent units of execution. Because data might be accessed simultaneously, Rust prevents "data races" by enforcing strict ownership rules. If you want to send data from a parent thread to a child thread, you must prove that the data is no longer needed in the parent. We achieve this by transferring ownership.

Sending Data with Channels

The most idiomatic way to move data is via an mpsc (multi-producer, single-consumer) channel. When you send() a value into a channel, the parent thread loses the ability to access that variable. The channel effectively acts as a bridge that moves the object's memory responsibility to the receiving thread.

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

let (tx, rx) = mpsc::channel();

thread::spawn(move || {
    let message = String::from("Data transferred!");
    tx.send(message).unwrap(); 
    // 'message' is gone from this scope!
});

let received = rx.recv().unwrap();
println!("Got: {}", received);

Protecting Shared State with Mutexes

Sometimes, you don’t want to move data, but rather share it. A Mutex (Mutual Exclusion) allows threads to take turns accessing data. When a thread calls .lock(), it gains exclusive ownership of the inner data. If the data is complex, we wrap it in an Arc (Atomic Reference Counter) to ensure the memory stays alive as long as at least one thread holds a reference to it.

The Mutex ensures that only one thread at a time has the "permission" to mutate the data. By combining Arc and Mutex, you create a thread-safe container that handles memory cleanup automatically once the last thread finishes its work.

Whether you use channels to pass the "baton" of ownership or a Mutex to gatekeep access, Rust’s compiler ensures that your data is never accessed in a way that causes corruption. You are effectively shifting the burden of safety from manual tracking to the ownership system itself.

Key Takeaway: Inter-thread transfer is achieved by either moving ownership through channels or using synchronization primitives like Mutexes to safely gate access to shared memory.