I have this code:
use std::sync::atomic::{AtomicUsize, Ordering};
const SOME_VAR: AtomicUsize = AtomicUsize::new(0);
fn main() {
println!("{}", SOME_VAR.load(Ordering::SeqCst));
println!("{}", SOME_VAR.fetch_add(10, Ordering::SeqCst));
println!("{}", SOME_VAR.load(Ordering::SeqCst));
}
This prints 0 0 0
without any errors. In Java, I can use a final HashMap
and add (k, v)
to it. In Rust, I am surprised that the compiler is not yelling at me but also does not increment my atomic value. Am I doing something wrong here?
If I use a static
:
static SOME_VAR: AtomicUsize = AtomicUsize::new(0);
I get the result 0 0 10
. Why does it not work with const
?
A static
variable is guaranteed to have a single instance and you can take a reference to it. A const
variable does not have this guarantee and the compiler is allowed to have zero, one, or multiple instances of it.
In your case, the code is equivalent to:
println!("{}", AtomicUsize::new(0).load(Ordering::SeqCst));
println!("{}", AtomicUsize::new(0).fetch_add(10, Ordering::SeqCst));
println!("{}", AtomicUsize::new(0).load(Ordering::SeqCst));
Since each value is created and thrown away, no changes from one propagate to the other.
In some ways, you can think of a const
variable like a C or C++ #define
— conceptually the value is just pasted wherever it's used.
Clippy 0.0.211 has a lint for this case:
error: a const item should never be interior mutable
--> src/main.rs:3:1
|
3 | const SOME_VAR: AtomicUsize = AtomicUsize::new(0);
| -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| help: make this a static item: `static`
|
= note: #[deny(declare_interior_mutable_const)] on by default
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.211/index.html#declare_interior_mutable_const
error: a const item with interior mutability should not be borrowed
--> src/main.rs:6:20
|
6 | println!("{}", SOME_VAR.load(Ordering::SeqCst));
| ^^^^^^^^
|
= note: #[deny(borrow_interior_mutable_const)] on by default
= help: assign this const to a local or static variable, and use the variable here
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.211/index.html#borrow_interior_mutable_const
In Java, I can use a
final HashMap
Yes, you can make a non-thread-safe HashMap
very easily in Java. Rust doesn't want to make it easy to create code that can lead to memory unsafety. You need to protect the type with appropriate safety, such as by a Mutex
, or you need to dip into unsafe
code if you the programmer guarantee that a global value will only ever be used by one thread.
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With