rust 如何更改线程中的结构?

hlswsv35  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(126)

请帮帮我,我完全糊涂了。
如何使此代码工作?
我需要更改线程中的结构成员...

#[derive(Debug)]
struct S {
    str: String,
    b: bool,
    i: u128,
}

fn main() {
    let mut vec_s = vec![];

    vec_s.push(S {
        str: "a".to_string(),
        b: false,
        i: 0,
    });

    let mut threads = vec![];

    for s in vec_s {
        {
            let mut _s = &s;
            threads.push(std::thread::spawn(move || {
                _s.b = true;
                _s.str = "b".to_string();
                _s.i = 1;
            }));
        }
    }

    for thread in threads {
        let _ = thread.join();
    }

    dbg!(&vec_s);
}

编译器会输出许多错误:

error[E0594]: cannot assign to `_s.b`, which is behind a `&` reference
  --> src/main.rs:23:17
   |
23 |                 _s.b = true;
   |                 ^^^^^^^^^^^ cannot assign

error[E0594]: cannot assign to `_s.str`, which is behind a `&` reference
  --> src/main.rs:24:17
   |
24 |                 _s.str = "b".to_string();
   |                 ^^^^^^ cannot assign

error[E0594]: cannot assign to `_s.i`, which is behind a `&` reference
  --> src/main.rs:25:17
   |
25 |                 _s.i = 1;
   |                 ^^^^^^^^ cannot assign

error[E0597]: `s` does not live long enough
  --> src/main.rs:21:26
   |
21 |               let mut _s = &s;
   |                            ^^ borrowed value does not live long enough
22 |               threads.push(std::thread::spawn(move || {
   |  __________________________-
23 | |                 _s.b = true;
24 | |                 _s.str = "b".to_string();
25 | |                 _s.i = 1;
26 | |             }));
   | |______________- argument requires that `s` is borrowed for `'static`
27 |           }
28 |       }
   |       - `s` dropped here while still borrowed

error[E0382]: borrow of moved value: `vec_s`
   --> src/main.rs:34:10
    |
9   |     let mut vec_s = vec![];
    |         --------- move occurs because `vec_s` has type `Vec<S>`, which does not implement the `Copy` trait
...
19  |     for s in vec_s {
    |              ----- `vec_s` moved due to this implicit call to `.into_iter()`
...
34  |     dbg!(&vec_s);
    |          ^^^^^^ value borrowed here after move
    |
note: this function takes ownership of the receiver `self`, which moves `vec_s`
   --> /home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:261:18
    |
261 |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
help: consider iterating over a slice of the `Vec<S>`'s content to avoid moving into the `for` loop
    |
19  |     for s in &vec_s {
    |              +
yhived7q

yhived7q1#

您正在尝试执行多线程。多线程访问的所有内容都必须是线程安全的。此外,Rust非常严格(零未定义行为容忍),编译器必须了解您的代码是线程安全的。
这里最大的问题是Rust的借位检查器不知道你的线程在某个点被加入。因此它不允许你创建对你的S对象的引用,因为它不能证明这些引用存在了多久。Rust必须能够证明它们在你的S对象被删除之前被销毁了;那是拉斯特借钱安全保证一部分
对于您的特定用例,Rust引入了thread scopes。通过它们,编译器最终可以了解线程的生存期。
修复了一些次要的所有权问题(对循环使用&mut vec_s,否则vec_s对象将被循环使用),现在可以这样做:
第一个
另一个优化:
如果你实际上并没有使用JoinHandle来传播错误或类似的东西,那么在这个例子中你根本就不需要它们。scope已经在作用域的末尾自动加入了它所产生的所有线程:
第一次

相关问题