Introduction
In Rust, Arc
stands for Atomic Reference Counting and is used for thread-safe reference counting. It allows you to share ownership of an immutable value across multiple threads. When the last reference to the value is dropped, the value is deallocated.
Using Arc
To use Arc
, you need to import it from the std::sync
module. You can create an Arc
by using the Arc::new
method. Cloning an Arc
increases its reference count, and when all clones are dropped, the value is deallocated.
use std::sync::Arc;
fn main() {
let value = Arc::new(5);
let value_clone = Arc::clone(&value);
println!("Value: {}", value);
println!("Cloned Value: {}", value_clone);
}
// Output:
// Value: 5
// Cloned Value: 5
Key Methods
Below are some of the key methods exposed by the Arc
class:
Arc::new
Creates a new Arc
instance.
use std::sync::Arc;
fn main() {
let value = Arc::new(10);
println!("Value: {}", value);
}
// Output:
// Value: 10
Arc::clone
Clones the Arc
, increasing the reference count.
use std::sync::Arc;
fn main() {
let value = Arc::new(15);
let value_clone = Arc::clone(&value);
println!("Value: {}", value);
println!("Cloned Value: {}", value_clone);
}
// Output:
// Value: 15
// Cloned Value: 15
Arc::strong_count
Returns the number of strong references to the Arc
.
use std::sync::Arc;
fn main() {
let value = Arc::new(20);
let value_clone = Arc::clone(&value);
println!("Reference Count: {}", Arc::strong_count(&value));
}
// Output:
// Reference Count: 2
Example Usage
Example 1: Basic Usage
use std::sync::Arc;
fn main() {
let value = Arc::new(30);
println!("Value: {}", value);
}
// Output:
// Value: 30
Example 2: Cloning Arc
use std::sync::Arc;
fn main() {
let value = Arc::new(35);
let value_clone = Arc::clone(&value);
println!("Value: {}", value);
println!("Cloned Value: {}", value_clone);
}
// Output:
// Value: 35
// Cloned Value: 35
Example 3: Reference Counting
use std::sync::Arc;
fn main() {
let value = Arc::new(40);
let value_clone1 = Arc::clone(&value);
let value_clone2 = Arc::clone(&value);
println!("Reference Count: {}", Arc::strong_count(&value));
}
// Output:
// Reference Count: 3
Example 4: Using Arc with Threads
use std::sync::Arc;
use std::thread;
fn main() {
let value = Arc::new(50);
let mut handles = vec![];
for _ in 0..5 {
let value_clone = Arc::clone(&value);
let handle = thread::spawn(move || {
println!("Value in thread: {}", value_clone);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
// Output (order may vary):
// Value in thread: 50
// Value in thread: 50
// Value in thread: 50
// Value in thread: 50
// Value in thread: 50
Example 5: Dropping Arc
use std::sync::Arc;
fn main() {
let value = Arc::new(60);
{
let value_clone = Arc::clone(&value);
println!("Reference Count: {}", Arc::strong_count(&value));
} // value_clone goes out of scope here
println!("Reference Count after drop: {}", Arc::strong_count(&value));
}
// Output:
// Reference Count: 2
// Reference Count after drop: 1
Considerations
Arc
is only for sharing immutable data between threads. For mutable data, consider usingMutex
orRwLock
along withArc
.- Cloning an
Arc
is cheap, as it only increments the reference count. - When all
Arc
references are dropped, the inner value is deallocated.