Multithreading 如何告诉Rust让我修改隐藏在rBlock后面的共享变量?
Safe要求从所有参考资料中获得以下信息:Multithreading 如何告诉Rust让我修改隐藏在rBlock后面的共享变量?,multithreading,rust,Multithreading,Rust,Safe要求从所有参考资料中获得以下信息: 对资源的一个或多个引用(&T) 只有一个可变引用(&mut T) 我希望有一个可以由多个线程读取和一个线程写入的Vec,但一次只能有一个线程(根据语言要求) 所以我使用了rblock 我需要一个Vec。为了让它比主函数更长寿,我将它放入框中,然后在其周围插入锁,如下所示: fn main() { println!("Hello, world!"); let mut v = vec![0, 1, 2, 3, 4, 5, 6]; l
&T
)&mut T
)Vec
,但一次只能有一个线程(根据语言要求)
所以我使用了rblock
我需要一个Vec
。为了让它比主函数更长寿,我将它放入框中,然后在其周围插入锁,如下所示:
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));
}
}
没有线程:
for i in 0..10 {
threadFunc(&val);
}
它编译。问题在于关闭。我必须“移动”它,否则Rust会抱怨它可以比main
更长寿,我也不能克隆val
(rBlock
没有实现clone()
)
我该怎么办?注意,使用
rBlock
和互斥锁之间没有结构上的区别;他们只是有不同的访问模式。看见
进行相关讨论
问题的核心是,您已经将向量的所有权(在rblock
中)转移到了某个线程;因此,你的主线程不再有它了。你无法访问它,因为它不见了
事实上,您将遇到与尝试将向量传递给每个线程相同的问题。你只有一个向量可以给出,所以只有一个线程可以得到它
您需要线程安全共享所有权,由以下人员提供:
使用std::sync::{Arc,RwLock};
使用std::线程;
使用std::time::Duration;
fn main(){
println!(“你好,世界!”);
设v=vec![0,1,2,3,4,5,6];
设val=Arc::new(RwLock::new(v));
对于0..10中的uu{
设v=val.clone();
线程::生成(移动| |线程| func(v));
}
对于0..5中的uu{
{
让mut val=val.write().unwrap();
val.push(1);
}
线程::睡眠(持续时间::从_毫秒(1000));
}
}
fn螺纹功能(val:Arc){
环路{
{
让val=val.read().unwrap();
println!(“{}”,val.len());
}
线程::睡眠(持续时间::从_毫秒(100));
}
}
其他需要注意的事项:
我删除了main
中的无限循环,以便代码能够真正完成
我修复了所有编译器警告。如果要使用编译语言,请注意警告。
- 不必要的括号
snake\u案例
标识符。明确地不要对局部变量使用PascalCase
;这是用于类型的camelCase
不用于生锈
我添加了一些块,以缩短读/写锁的使用寿命。否则会有很多争用,并且子线程永远没有机会获得读锁
let ref v1=*(*foo)代码>是非惯用的。首选让v1=&**foo
。由于Deref
,您甚至不需要这样做
请注意,使用RwLock
和互斥体之间没有结构上的区别;他们只是有不同的访问模式。看见
进行相关讨论
问题的核心是,您已经将向量的所有权(在rblock
中)转移到了某个线程;因此,你的主线程不再有它了。你无法访问它,因为它不见了
事实上,您将遇到与尝试将向量传递给每个线程相同的问题。你只有一个向量可以给出,所以只有一个线程可以得到它
您需要线程安全共享所有权,由以下人员提供:
使用std::sync::{Arc,RwLock};
使用std::线程;
使用std::time::Duration;
fn main(){
println!(“你好,世界!”);
设v=vec![0,1,2,3,4,5,6];
设val=Arc::new(RwLock::new(v));
对于0..10中的uu{
设v=val.clone();
线程::生成(移动| |线程| func(v));
}
对于0..5中的uu{
{
让mut val=val.write().unwrap();
val.push(1);
}
线程::睡眠(持续时间::从_毫秒(1000));
}
}
fn螺纹功能(val:Arc){
环路{
{
让val=val.read().unwrap();
println!(“{}”,val.len());
}
线程::睡眠(持续时间::从_毫秒(100));
}
}
其他需要注意的事项:
我删除了main
中的无限循环,以便代码能够真正完成
我修复了所有编译器警告。如果要使用编译语言,请注意警告。
- 不必要的括号
snake\u案例
标识符。明确地不要对局部变量使用PascalCase
;这是用于类型的camelCase
不用于生锈
我添加了一些块,以缩短读/写锁的使用寿命。否则会有很多争用,并且子线程永远没有机会获得读锁
let ref v1=*(*foo)代码>是非惯用的。首选让v1=&**foo
。由于Deref
,您甚至不需要这样做
谢谢,不过drop()
变量不是比破解作用域更惯用吗?@CharlesShiller。因此,不,块是最常用的。@E_net4在这种情况下,drop
应该可以工作,因为锁看起来不像是可变的借用。我不知道其中一个比另一个更地道drop(vec)
对我来说只是有些奇怪。另外,可能是我身上的C,但是&**foo
与*foo
不同吗?@Charleshiller请查看详细信息。TL;DR,Rust具有Deref
的特性,这意味着&*
并不总是不可操作的。谢谢,尽管它不是更习惯于
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));
}
}