为何Rust中const原子变量无法更新,static原子变量却可以?
const AtomicUsize get updated in Rust, but static AtomicUsize does? Great question! The core issue here is that Rust's const and static have completely different semantics—they're not interchangeable, and they don't map directly to Java's final keyword like you might expect. Let's break this down:
First: What const actually does in Rust
When you define a value with const, you're creating a compile-time constant. Every time you reference that constant in your code, the compiler copies the entire value into that location.
In your original code, that means:
- The first
SOME_VAR.load()uses a brand-newAtomicUsize::new(0)instance - The
SOME_VAR.fetch_add(10, ...)uses another brand-new instance (so it increments 0 to 10, but this instance is discarded immediately after the call) - The final
SOME_VAR.load()uses yet another brand-new instance, which starts at 0 again
That's exactly why you see 0 0 0—you're never modifying the same atomic variable twice!
Then: What static does in Rust
A static variable defines a single global instance that lives for the entire duration of your program. Every reference to SOME_VAR points to the same memory address, so all operations modify that one shared value.
When you switch to static:
- The first
load()reads the initial 0 from the global instance fetch_add(10, ...)modifies that same global instance (returning the original value 0, then setting it to 10)- The final
load()reads the updated 10 from the global instance
Which gives you the expected 0 0 10 output.
How this differs from Java's final
Java's final HashMap only prevents you from reassigning the variable to a different HashMap instance—the underlying map itself is still mutable. Rust's const is nothing like this: it's a compile-time value that gets duplicated everywhere it's used, so you can't use it to hold mutable global state at all.
Code examples for clarity
The problematic const version
use std::sync::atomic::{AtomicUsize, Ordering}; // Each use creates a NEW AtomicUsize instance! const SOME_VAR: AtomicUsize = AtomicUsize::new(0); fn main() { // Uses instance #1 (value: 0) println!("{}", SOME_VAR.load(Ordering::SeqCst)); // Uses instance #2 (increments 0 to 10, returns 0, then discards it) println!("{}", SOME_VAR.fetch_add(10, Ordering::SeqCst)); // Uses instance #3 (value: 0) println!("{}", SOME_VAR.load(Ordering::SeqCst)); }
The working static version
use std::sync::atomic::{AtomicUsize, Ordering}; // Single global instance, shared across all uses static SOME_VAR: AtomicUsize = AtomicUsize::new(0); fn main() { // Reads the global instance (initial value: 0) println!("{}", SOME_VAR.load(Ordering::SeqCst)); // Modifies the global instance: returns 0, sets it to 10 println!("{}", SOME_VAR.fetch_add(10, Ordering::SeqCst)); // Reads the updated global instance (value: 10) println!("{}", SOME_VAR.load(Ordering::SeqCst)); }
Key takeaway
If you need a mutable global state (like an atomic counter), always use static (atomic types are safe to use with static because their operations are thread-safe by design). const is only for values that are fixed at compile time and don't need to change at runtime—every reference to a const is a separate copy.
内容的提问来源于stack exchange,提问作者misnomer___

