【问题标题】:Why are const atomic variables not updated, but static atomic variables are?为什么 const 原子变量没有更新,而静态原子变量却更新了?
【发布时间】:2018-05-31 19:06:36
【问题描述】:

我有这个代码:

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

【问题讨论】:

  • Rust 没有任何类似于 Java 的 final 的东西,因为它不支持继承并且默认情况下变量是不可变的。 Java 没有任何类似于 Rust 的 const 的东西,因为 Java 倾向于依赖 JVM 来优化事物,而不是进行编译时评估。 Rust 的 const 更像 C++ 的 constexpr,Java 的 final 更像 C++ 的 const。清如泥!

标签: rust


【解决方案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 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,或者如果您是程序员保证全局值只会被一个线程。

另见:

【讨论】:

    猜你喜欢
    • 2020-05-21
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多