Introduction
The AtomicISize
class in Rust provides a way to perform atomic operations on a platform-dependent signed integer. It is part of Rust's standard library and is typically used for safe concurrent programming, allowing multiple threads to manipulate shared data without introducing data races.
Using AtomicISize
The AtomicISize
class can be used to create a thread-safe integer that supports atomic operations. Here is a basic example:
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(5);
atomic_val.store(10, Ordering::SeqCst);
let value = atomic_val.load(Ordering::SeqCst);
println!("Value: {}", value);
}
// Output: Value: 10
Key Methods
Below are some of the key methods exposed by the AtomicISize
class:
new
Creates a new AtomicISize
initialized to the given value.
use std::sync::atomic::AtomicISize;
fn main() {
let atomic_val = AtomicISize::new(0);
println!("Initial value: {}", atomic_val.load(Ordering::SeqCst));
}
// Output: Initial value: 0
load
Loads a value from the AtomicISize
. Takes an Ordering
argument to specify the memory ordering of the operation.
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
let value = atomic_val.load(Ordering::Relaxed);
println!("Loaded value: {}", value);
}
// Output: Loaded value: 1
store
Stores a value into the AtomicISize
. Takes an Ordering
argument to specify the memory ordering of the operation.
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
atomic_val.store(2, Ordering::Relaxed);
println!("Stored value: {}", atomic_val.load(Ordering::Relaxed));
}
// Output: Stored value: 2
swap
Swaps the current value with a new value. Returns the previous value. Takes an Ordering
argument to specify the memory ordering of the operation.
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
let old_value = atomic_val.swap(3, Ordering::SeqCst);
println!("Old value: {}, New value: {}", old_value, atomic_val.load(Ordering::SeqCst));
}
// Output: Old value: 1, New value: 3
compare_and_swap
Compares the current value with a specified value and, if they are equal, sets the current value to a new value. Returns the previous value. This method is deprecated in favor of compare_exchange
.
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
let old_value = atomic_val.compare_and_swap(1, 4, Ordering::SeqCst);
println!("Old value: {}, New value: {}", old_value, atomic_val.load(Ordering::SeqCst));
}
// Output: Old value: 1, New value: 4
fetch_add
Adds to the current value, returning the previous value. Takes an Ordering
argument to specify the memory ordering of the operation.
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
let prev_value = atomic_val.fetch_add(5, Ordering::SeqCst);
println!("Previous value: {}, Current value: {}", prev_value, atomic_val.load(Ordering::SeqCst));
}
// Output: Previous value: 1, Current value: 6
fetch_sub
Subtracts from the current value, returning the previous value. Takes an Ordering
argument to specify the memory ordering of the operation.
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(10);
let prev_value = atomic_val.fetch_sub(3, Ordering::SeqCst);
println!("Previous value: {}, Current value: {}", prev_value, atomic_val.load(Ordering::SeqCst));
}
// Output: Previous value: 10, Current value: 7
Example Usage
Example 1: Basic Initialization and Load
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(42);
let value = atomic_val.load(Ordering::SeqCst);
println!("Loaded value: {}", value);
}
// Output: Loaded value: 42
Example 2: Atomic Store
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(5);
atomic_val.store(10, Ordering::SeqCst);
println!("Stored value: {}", atomic_val.load(Ordering::SeqCst));
}
// Output: Stored value: 10
Example 3: Atomic Swap
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
let old_value = atomic_val.swap(3, Ordering::SeqCst);
println!("Old value: {}, New value: {}", old_value, atomic_val.load(Ordering::SeqCst));
}
// Output: Old value: 1, New value: 3
Example 4: Compare and Swap
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
let old_value = atomic_val.compare_and_swap(1, 4, Ordering::SeqCst);
println!("Old value: {}, New value: {}", old_value, atomic_val.load(Ordering::SeqCst));
}
// Output: Old value: 1, New value: 4
Example 5: Fetch Add
use std::sync::atomic::{AtomicISize, Ordering};
fn main() {
let atomic_val = AtomicISize::new(1);
let prev_value = atomic_val.fetch_add(5, Ordering::SeqCst);
println!("Previous value: {}, Current value: {}", prev_value, atomic_val.load(Ordering::SeqCst));
}
// Output: Previous value: 1, Current value: 6
Considerations
AtomicISize
provides low-level atomic operations for concurrency. Proper use of memory ordering (e.g.,Ordering::Relaxed
,Ordering::SeqCst
) is essential to ensure correctness.- Using atomic operations can be complex and error-prone; consider higher-level synchronization primitives like mutexes if simpler concurrency management is needed.
See Also
- AtomicUSize - Similar to
AtomicISize
, but for unsigned platform-dependent integers. - Mutex - A mutual exclusion primitive useful for protecting shared data.
- RwLock - A reader-writer lock for allowing concurrent reads or exclusive writes.
- Arc - An atomic reference-counted smart pointer for shared ownership across threads.