记录rust滥用lazy_static导致的一个bug
本质就是lock以后task crash
后导致其他线程饿死;在cpp20的coroutine也有类似场景
1. 模拟代码
toml
[package]
name = "rust-crash-collect-20250611"
version = "0.1.0"
edition = "2024"
[dependencies]
tokio = { version = "1.40.0", features = ["full"] }
lazy_static = "1.5.0"
代码
rust
use std::sync::Mutex;
lazy_static::lazy_static! {
static ref COUNTER: Mutex<i32> = Mutex::new(0);
}
struct raii {
name: String,
}
impl Drop for raii {
fn drop(&mut self) {
println!("Dropping raii");
}
}
#[tokio::main]
async fn main() {
for cnt in 0..10 {
tokio::spawn(async move {
let raii = raii {
name: format!("raii {}", cnt),
};
let mut counter = COUNTER.lock();
match counter {
Ok(mut counter) => {
*counter += 1;
println!("counter: {}", *counter);
if *counter == 5 {
panic!("Counter is 5");
}
}
Err(e) => {
println!("Error: {}", e);
}
}
});
}
loop {}
}
1.1 执行结果
sh
cargo run

2. 解决方案
2.1 如果task不依赖其他组件
因业务上tokio
的spawn
的task
可以移除lock
且能够独立,故将变量以move
的形式实现。
2.2 如果task有依赖
暂没思路
3. 经验
- 在multi thread编程中,尽量使用纯函数,不要过多依赖全局变量
- 如果有依赖尽量使用dag这样的框架,而不是手写依赖