Arc
Imagine a Rust program that starts 10 threads, but wants to access a Vec
from all of the threads. We could copy the type, but an Arc
is a better option.
With Arc
, we indicate an atomic reference count is wanted. Atomic refers to the thread-safe nature of Arc
. Arc
can be used on multiple threads with no worries.
This rust program includes the Arc
type at the top. We create a Vector
of many integers, and then create an Arc
reference to the Vec
.
Arc
, we call Arc::new()
on a type like a vector or struct
instance. Even a string
can be in an Arc
.Arc
, and then we call clone()
on the Arc
reference to allow other types to access the Arc
.use std::thread; use std::sync::Arc; fn main() { // Create Vec of many integers. let mut data: Vec<i32> = vec![]; for i in 0..100000 { data.push(i); } // Create Arc of the vector. let data_ref: Arc<Vec<i32>> = Arc::new(data); // Clone the Arc across 10 vector elements. let mut vector = vec![]; for _ in 0..10 { vector.push(data_ref.clone()); } // Create a thread for each group and access the vector from the Arc. let mut children = vec![]; for x in vector { children.push(thread::spawn(move || { // The array of many integers is available through the Arc. println!("{}", x.len()); })); } // Done. for child in children { let _ = child.join(); } }100000 100000 100000 100000 100000 100000 100000 100000 100000 100000
Many threads can access data through an Arc
reference. But none of them can modify the data—if we try this, we get a compile error in Rust.
error[E0596]: cannot borrow data in an `Arc` as mutable
Arcs seem to lead to significant performance wins in Rust programs that must use shared data. Copying data can be slow, particularly if the data is large.
Arc
versus Rc
In Rust an Arc
is an atomic reference count element. The "atomic" part refers to its thread safety. An Rc
is just a reference count, but it cannot be passed to threads.
Rc
is passed to a thread. A program won't compile.The Arc
type, part of the std sync library, is powerful and can vastly optimize Rust programs. It has limitations, but it is a key and important part of Rust threading.