tokio 读写锁死锁例子
一个简单的 tokio rw 锁 死锁例子:
use std::sync::Arc;
use tokio::{
self,
runtime::Runtime,
sync,
time::{self, Duration},
};
fn main() {
let rt = Runtime::new().unwrap();
rt.block_on(async {
let rwlock = Arc::new(sync::RwLock::new(0));
let lock1 = rwlock.clone();
tokio::spawn(async move {
let _read1 = lock1.read().await;
time::sleep(Duration::from_secs(2)).await;
let _read2 = lock1.read().await;
});
time::sleep(Duration::from_secs(1)).await;
let mut write1 = rwlock.write().await;
*write1 = 2;
});
println!("task done .");
std::process::exit(-1);
}
简单说一下代码的执行过程。
第14行获取读取锁,然后子任务休眠2秒。
代码跳出子任务,执行18行的休眠1秒。
休眠结束,19行获取写入锁。
两秒结束,16行再次尝试获取读取锁。
第14行是首次获取读取锁,此时肯定是可以成功获取的。_read1 持有读取锁,并未释放。
19行获取写入锁,但是因为14行获取的读取锁还未释放。获取失败,等待中。
16行获取读取锁,但是19行还在等待14行的读取锁释放。
此时陷入死锁。
为了尽量避免死锁的出现。我们应该在每次使用完锁之后尽快的释放它。比如:
use std::sync::Arc;
use tokio::{
self,
runtime::Runtime,
sync,
time::{self, Duration},
};
fn main() {
let rt = Runtime::new().unwrap();
rt.block_on(async {
let rwlock = Arc::new(sync::RwLock::new(0));
let lock1 = rwlock.clone();
tokio::spawn(async move {
let read1 = lock1.read().await;
drop(read1);
time::sleep(Duration::from_secs(2)).await;
let read2 = lock1.read().await;
drop(read2);
});
time::sleep(Duration::from_secs(1)).await;
let mut write1 = rwlock.write().await;
*write1 = 2;
drop(write1);
});
println!("task done .");
std::process::exit(-1);
}
本文来自博客园,作者:贤云曳贺,转载请注明原文链接:https://www.cnblogs.com/SantiagoZhang/p/16525257.html