gpt4 book ai didi

multithreading - 如何告诉 Rust 让我修改隐藏在 RwLock 后面的共享变量?

转载 作者:行者123 更新时间:2023-11-29 08:27:20 25 4
gpt4 key购买 nike

安全 Rust要求所有引用资料如下:

  1. 对资源的一次或多次引用 ( &T ),
  2. 只有一个可变引用 ( &mut T )。

我想要一个Vec可以由多个线程读取并由一个线程写入,但一次只能有一个(根据语言要求)。

所以我使用 RwLock .

我需要一个 Vec<i8> .为了让它比主要功能长寿,我 Box它然后我RwLock围绕那个,像这样:

fn main() {
println!("Hello, world!");
let mut v = vec![0, 1, 2, 3, 4, 5, 6];
let val = RwLock::new(Box::new(v));
for i in 0..10 {
thread::spawn(move || threadFunc(&val));
}
loop {
let mut VecBox = (val.write().unwrap());
let ref mut v1 = *(*VecBox);
v1.push(1);
//And be very busy.
thread::sleep(Duration::from_millis(10000));
}
}
fn threadFunc(val: &RwLock<Box<Vec<i8>>>) {
loop {
//Use Vec
let VecBox = (val.read().unwrap());
let ref v1 = *(*VecBox);
println!("{}", v1.len());
//And be very busy.
thread::sleep(Duration::from_millis(1000));
}
}

Rust 拒绝编译这个:

 capture of moved value: `val`
--> src/main.rs:14:43
|
14 | thread::spawn(move || threadFunc(&val));
| ------- ^^^ value captured here after move
| |
| value moved (into closure) here

没有线程:

for i in 0..10 {
threadFunc(&val);
}

它编译。问题在于闭包。我必须“移动”它,否则 Rust 会提示它可能比 main 还长, 我也无法克隆 val ( RwLock 没有实现 clone() )。

我该怎么办?

最佳答案

请注意,使用 RwLockMutex 之间没有结构上的区别;他们只是有不同的访问模式。看 Concurrent access to vector from multiple threads using a mutex lock进行相关讨论。

问题的核心在于您已将向量的所有权(在 RwLock 中)转移到某个线程;因此,您的主线程不再拥有它。您无法访问它,因为它已消失。

事实上,您将遇到与您尝试将矢量传递给每个线程相同的问题。您只有一个向量可以提供,因此只有一个线程可以拥有它。

您需要线程安全的共享所有权,由Arc 提供:

use std::sync::{Arc, RwLock};
use std::thread;
use std::time::Duration;

fn main() {
println!("Hello, world!");
let v = vec![0, 1, 2, 3, 4, 5, 6];
let val = Arc::new(RwLock::new(v));

for _ in 0..10 {
let v = val.clone();
thread::spawn(move || thread_func(v));
}

for _ in 0..5 {
{
let mut val = val.write().unwrap();
val.push(1);
}
thread::sleep(Duration::from_millis(1000));
}
}

fn thread_func(val: Arc<RwLock<Vec<i8>>>) {
loop {
{
let val = val.read().unwrap();
println!("{}", val.len());
}
thread::sleep(Duration::from_millis(100));
}
}

其他注意事项:

  1. 我删除了 main 中的无限循环,这样代码才能真正完成。
  2. 我修复了所有编译器警告。如果您打算使用编译语言,请注意警告。
    • 不必要的括号
    • snake_case 标识符。绝对不要对局部变量使用PascalCase;用于类型。 camelCase 未在 Rust 中使用。
  3. 我添加了一些 block 来缩短读/写锁的生命周期。否则会有很多争用,子线程永远没有机会获得读锁。
  4. let ref v1 = *(*foo); 不是惯用语。首选 let v1 = &**foo。多亏了 Deref,您甚至根本不需要这样做。

关于multithreading - 如何告诉 Rust 让我修改隐藏在 RwLock 后面的共享变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43592247/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com