У меня есть этот код:
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));
}
Это печатает 0 0 0
без каких-либо ошибок. В Java я могу использовать final HashMap
и добавлять (k, v)
к нему. В Rust я удивлен, что компилятор не кричит на меня, но также не увеличивает мою атомную ценность. Я здесь что-то не так?
Если я использую static
:
static SOME_VAR: AtomicUsize = AtomicUsize::new(0);
Я получаю результат 0 0 10
. Почему это не работает с const
?
Ответ 1
static
переменная гарантированно имеет один экземпляр, и вы можете ссылаться на нее. const
переменная не имеет этой гарантии, и компилятору разрешено иметь нулевой, один или несколько экземпляров.
В вашем случае код эквивалентен:
println!("{}", AtomicUsize::new(0).load(Ordering::SeqCst));
println!("{}", AtomicUsize::new(0).fetch_add(10, Ordering::SeqCst));
println!("{}", AtomicUsize::new(0).load(Ordering::SeqCst));
Поскольку каждое значение создается и отбрасывается, никакие изменения от одного не распространяются на другие.
В некотором смысле, вы можете думать о const
переменной как C или C++ #define
- концептуально значение только что вставили там, где она используется.
Clippy 0.0.211 имеет ворсину для этого случая:
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
В Java я могу использовать final HashMap
Да, вы можете сделать не-поточно- HashMap
очень легко в Java. Rust не хочет упрощать создание кода, который может привести к ненадежности памяти. Вам необходимо защитить тип с соответствующей безопасностью, например, с помощью Mutex
, или вам нужно окунуться в unsafe
код, если вы программист гарантируете, что глобальное значение будет использоваться только одним потоком.
Смотрите также: