为什么const原子变量没有更新,但静态原子变量是?

时间:2018-05-31 19:06:37

标签: rust

我有这段代码:

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 个答案:

答案 0 :(得分:13)

保证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 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
  

在Java中,我可以使用final HashMap

是的,您可以非常轻松地在Java中创建非线程安全 HashMap。 Rust并不想让创建可能导致内存不安全的代码变得容易。您需要保护具有适当安全性的类型,例如Mutex,或者如果您的程序员保证只有全局值,您需要使用unsafe代码永远被一个线程使用。

另见: