为什么 2021 年 12 月 18 日的 Rust 代码能够编译?

问题描述 投票:0回答:1

this博客文章中,作者表明 Rust 不允许通过引用捕获变量:

use std::thread;
use std::sync::atomic::{AtomicI32, Ordering};

struct ThreadSafeCounter {
    count: AtomicI32,
}

impl ThreadSafeCounter {
    fn increment(&mut self) { self.count.fetch_add(1, Ordering::SeqCst); }
}

pub fn main() {
    let n = 10;
    let mut counter = ThreadSafeCounter { count: AtomicI32::new(0) };
    let mut threads = Vec::new();
    for _ in 0..n {
        threads.push(thread::spawn( || {
            // Rust won't allow this.  We are attempting to mutably borrow
            // the same value multiple times.
            counter.increment();
        }));
    }
    for thread in threads { thread.join(); }
    println!("{}", counter.count.load(Ordering::SeqCst));
}

然后对代码进行一项更改,并表示:

Rust 对线程安全的回答是允许对不可变对象进行突变 参考。 Rust 称之为“内部可变性”。带着一个小 更改后,前面的示例将按预期编译并工作:

use std::thread;
use std::sync::atomic::{AtomicI32, Ordering};

struct ThreadSafeCounter {
    count: AtomicI32,
}

impl ThreadSafeCounter {
    // increment() uses "interior mutability": it accepts an immutable
    // reference, but ultimately mutates the value.
    fn increment(&self) { self.count.fetch_add(1, Ordering::SeqCst); }
}

pub fn main() {
    let n = 10;
    let mut counter = ThreadSafeCounter { count: AtomicI32::new(0) };
    let mut threads = Vec::new();
    for _ in 0..n {
        threads.push(thread::spawn( || {
            counter.increment();
        }));
    }
    for thread in threads { thread.join(); }
    println!("{}", counter.count.load(Ordering::SeqCst));
}

我得到的错误是:

强制关闭取得

counter
(以及任何其他 引用的变量),使用
move
关键字:

这应该可以编译吗?该帖子写于 2021 年 12 月 18 日。

rust
1个回答
0
投票

博客文章不正确。该代码无法在任何 Rust 版本(2015、2018 或 2021)下编译,原因有两个:

  1. 生命周期:
    counter
    存在于
    main
    的堆栈中,因此它最终会超出范围。生成的线程只要正在执行就需要访问。
  2. 所有权转移:一旦通过将
    move
    放入第一个生成的线程中解决了生命周期问题,
    counter
    将不可用于后续生成的线程。
    
    
  3. 使其编译的最直接方法是
counter

一个新的

move
计数器引用到每个生成的线程中:
Arc

	
© www.soinside.com 2019 - 2024. All rights reserved.