19.7 Shared Ownership Across Threads with Arc<T>

Rc<T> enables shared ownership in single-threaded contexts but is not thread-safe. To share data across threads, Rust provides Arc<T> (Atomic Reference Counted). Arc<T> is similar to Rc<T> but uses atomic operations to update the reference count, ensuring correctness and safety in multi-threaded environments.

19.7.1 Arc<T>: Thread-Safe Shared Ownership

Arc<T> works like Rc<T> but with thread safety guaranteed by atomic increments and decrements of the reference count. Atomic operations are hardware-supported, low-level instructions that ensure data integrity when accessed concurrently by multiple threads.

Example:

use std::sync::Arc;
use std::thread;

fn main() {
    let data = Arc::new(42);
    let handles: Vec<_> = (0..4).map(|_| {
        let data = Arc::clone(&data);
        thread::spawn(move || {
            println!("Data: {}", data);
        })
    }).collect();
    for handle in handles {
        handle.join().unwrap();
    }
}

To allow mutation of shared data across threads, Arc<T> is often combined with synchronization primitives like Mutex<T> or RwLock<T>.

Example:

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

fn main() {
    let data = Arc::new(Mutex::new(0));
    let handles: Vec<_> = (0..4).map(|_| {
        let data = Arc::clone(&data);
        thread::spawn(move || {
            let mut val = data.lock().unwrap();
            *val += 1;
        })
    }).collect();
    for handle in handles {
        handle.join().unwrap();
    }
    println!("Final value: {}", *data.lock().unwrap());
}

19.7.2 When to Use Arc<T>

  • When multiple threads need to share read-only access to data.
  • In combination with Mutex<T> or RwLock<T> for shared, mutable data across threads.