[英]RwLock in a thread::spawn doesn't release the lock
我不知道為什么它掛在my.rw.write();
.
如果您取消對sleep
呼叫的注釋,則它可以正常工作。 這意味着在執行 spawn 線程並釋放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();
}
執行 spawn 線程並釋放
RwLock
后,寫訪問嘗試仍在阻塞主線程
這是不正確的。 添加基本調試輸出以區分它們表明唯一運行的println
是main
那個。
無法保證在產生子線程后哪個線程將首先執行。 但是,主線程可能會繼續運行,因為它已經在運行。 如果是這樣,它將通過rw
鎖定RwLock
並保持鎖定直到函數結束。 但是在函數結束之前,主線程會阻塞等待子線程的加入。 子線程無法完成,因為它必須先獲取寫鎖。 你創造了一個經典的僵局。
要解決此問題,請使用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
很可能會導致子線程先執行。 然后它將獲取鎖並退出,允許主線程繼續。
也可以看看:
它不能正常工作的原因是當主線程中的鎖在子線程中的鎖之前執行時,我沒有釋放鎖。 我像下面一樣修復它。
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.