我不确定为什么它会挂在my.rw.write();
上。
如果您取消对sleep
调用的注释,则可以正常使用。这意味着在执行派生线程并释放RwLock
之后,写访问尝试仍将阻塞主线程。我认为理论上一定很好。我在哪里错了?
use std::sync::Arc;
use std::sync::RwLock;
use std::{thread, time};
struct MySt {
num1: i64,
num2: i64,
rw: RwLock<Vec<i64>>,
}
fn main() {
let my = Arc::new(MySt {
num1: 32,
num2: 64,
rw: RwLock::new(vec![1, 2, 3]),
});
let my2 = my.clone();
let t = thread::spawn(move || {
let mut rw = my2.rw.write().unwrap();
rw[0] = 5;
println!("child thread {}, {}, {}, {}", my2.num1, my2.num2, rw[0], rw[1]);
});
//thread::sleep(time::Duration::from_millis(1000));
let mut rw = my.rw.write().unwrap();
rw[1] = 6;
println!("main thread {}, {}, {}, {}", my.num1, my.num2, rw[0], rw[1]);
t.join().unwrap();
}
答案 0 :(得分:2)
执行了派生线程并释放了
之后,写访问尝试仍在阻塞主线程。RwLock
这是不正确的。添加基本调试输出以区分它们,则表明运行的唯一println
是main
中的那个。
不能保证在生成子线程之后哪个线程将首先执行。但是,主线程可能可以继续运行,因为它已经在运行。如果是这样,它将通过RwLock
锁定rw
并按住直到功能结束。但是,在函数结束之前,主线程将阻塞等待子线程的加入。子线程无法完成,因为它必须先获得写锁定。您已经创建了经典的死锁。
要解决此问题,请使用drop
显式解锁锁,或添加范围以限制锁的寿命:
fn main() {
let my = Arc::new(MySt {
num1: 32,
num2: 64,
rw: RwLock::new(vec![1, 2, 3]),
});
let my2 = my.clone();
let t = thread::spawn(move || {
let mut rw = my2.rw.write().unwrap();
rw[0] = 5;
println!("thread a {}, {}, {}, {}", my2.num1, my2.num2, rw[0], rw[1]);
});
//thread::sleep(time::Duration::from_millis(1000));
let mut rw = my.rw.write().unwrap();
rw[1] = 6;
println!("thread b {}, {}, {}, {}", my.num1, my.num2, rw[0], rw[1]);
drop(rw);
t.join().unwrap();
}
添加sleep
可能会导致子线程首先执行。然后它将获取锁定并退出,从而允许主线程继续进行。
另请参阅:
答案 1 :(得分:0)
它不能正常工作的原因是,在子线程中的一个线程之前执行主线程中的锁定时,我没有释放锁定。我将其固定如下。
use std::sync::Arc;
use std::sync::RwLock;
use std::{thread, time};
struct MySt {
num1: i64,
num2: i64,
rw: RwLock<Vec<i64>>,
}
fn main() {
let my = Arc::new(MySt {
num1: 32,
num2: 64,
rw: RwLock::new(vec![1, 2, 3]),
});
let my2 = my.clone();
let t = thread::spawn(move || {
let mut rw = my2.rw.write().unwrap();
rw[0] = 5;
println!("child thread {}, {}, {}, {}", my2.num1, my2.num2, rw[0], rw[1]);
});
{
let mut rw = my.rw.write().unwrap();
rw[1] = 6;
println!("main thread {}, {}, {}, {}", my.num1, my.num2, rw[0], rw[1]);
}
t.join().unwrap();
}