为什么不更新 const 原子变量,但静态原子变量? [英] Why are const atomic variables not updated, but static atomic variables are?

查看:51
本文介绍了为什么不更新 const 原子变量,但静态原子变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码:

use std::sync::atomic::{AtomicUsize, Ordering};const SOME_VAR: AtomicUsize = AtomicUsize::new(0);fn 主(){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?

解决方案

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 有针对这种情况的 lint:

错误:const 项不应该是内部可变的-->src/main.rs:3:1|3 |const SOME_VAR: AtomicUsize = AtomicUsize::new(0);|-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|||帮助:使它成为一个静态项目:`static`|= 注意:#[deny(declare_interior_mutable_const)] 默认开启= 帮助:有关更多信息,请访问 https://rust-lang-nursery.github.io/rust-clippy/v0.0.211/index.html#declare_interior_mutable_const错误:不应借用具有内部可变性的常量项-->src/main.rs:6:20|6 |println!("{}", SOME_VAR.load(Ordering::SeqCst));|^^^^^^^^^|= 注意:#[deny(borrow_interior_mutable_const)] 默认开启= help: 将此常量分配给局部或静态变量,并在此处使用该变量= 帮助:有关更多信息,请访问 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 代码一个全局值只会被一个线程使用.

另见:

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:

这篇关于为什么不更新 const 原子变量,但静态原子变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆