虽然我已经阅读了所有OP、答案和Why do I get a deadlock when using Tokio with a std::sync::Mutex?的 comments ,但我还不明白为什么OP中的代码永远阻塞.
以下是原始代码的略有更改的版本:
use std::sync::Arc;
use std::sync::Mutex;
// use tokio::sync::Mutex;
use tokio::time::Duration;
async fn f(mtx: Arc<Mutex<i32>>, index: usize) {
println!("{}: trying to lock...", index);
{
let mut v = mtx.lock().unwrap();
// let mut v = mtx.lock().await;
println!("{}: locked", index);
tokio::time::sleep(Duration::from_millis(1)).await;
*v += 1;
}
println!("{}: unlocked", index);
}
#[tokio::main]
async fn main() {
let mtx = Arc::new(Mutex::new(0));
tokio::join!(f(mtx.clone(), 1), f(mtx.clone(), 2));
}
输出是
1: trying to lock...
1: locked
2: trying to lock...
(and blocks forever...)
根据答案和 comments (如果我没有看错),原因是the entire code is executed in a single-threaded environment.如果italicized部分是真的,我就能理解屏蔽行为了.然而,我不明白italicized部分是否真的是真的.
据我了解,
-
Tokio的默认运行时是多线程的,除非您显式指定
#[tokio::main(flavor = "current_thread")]
(source) -
并且
await
任务can被自动移动到另一个工作线程(source).
因此,我认为如果任务(即f(mtx.clone(), 1).await
、f(mtx.clone(), 2).await
和sleep(...).await
)是chosen(根据Tokio运行时)将在不同线程中执行,代码不会阻塞,但代码looks会阻塞,因为运行时happens Select 任务都在同一个线程中执行.
我的理解正确吗?