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
Arcis only for sharing immutable data between threads. For mutable data, consider usingMutexorRwLockalong withArc.- Cloning an
Arcis cheap, as it only increments the reference count. - When all
Arcreferences are dropped, the inner value is deallocated.
