multithreading - rust tui 应用程序中的并发 - 锁饥饿问题
问题描述
我有一个 tui 应用程序(使用tui-rs
crate 构建),其状态位于全局AppState
结构中。
该应用程序有 2 个线程:
- 主线程循环将内容绘制到屏幕上。它需要一个不可变的引用来
AppState
进行绘图。 - 偶尔会产生第二个线程来执行一些 CPU 繁重的工作。因此,它需要更新
AppState
,因此需要一个可变引用。
pub fn draw_screen() -> Result<(), Box<dyn Error>> {
let mut terminal = init_terminal().unwrap();
// prepare app state
let mut state = AppState::fresh_state();
let arc_state = Arc::new(Mutex::new(state));
loop {
terminal.draw(|f| {
// needs an immutable reference to AppState
do_some_drawing(arc_state.clone());
});
// needs a mutable reference to AppState
thread::spawn(|| {
do_some_calc(arc_state.clone());
});
}
Ok(())
}
目前这会导致应用程序挂起。主线程一直在循环中旋转,从而防止互斥锁被释放。这意味着第二个线程永远无法完成它的工作。这反过来意味着主线程(已经检查了工作是否已经完成)不断产生更多的工作线程,没有一个可以继续。
至少这是我对正在发生的事情的最佳猜测。
万一这很重要,这就是我在不可变和可变情况下访问互斥锁的方式:
// when I need an immutable ref
let lock = thread_state.lock().unwrap();
let state = lock.deref();
// when I need a mutable ref
let mut lock = thread_state.lock().unwrap();
let state = lock.deref_mut();
解决上述情况的正确方法是什么?
我一直在阅读有关RefCell
和频道的信息,但我没有足够的经验来拨打电话。希望得到一些指导(任何指向教程/文档的链接都非常受欢迎)。