首页 > 解决方案 > rust tui 应用程序中的并发 - 锁饥饿问题

问题描述

我有一个 tui 应用程序(使用tui-rscrate 构建),其状态位于全局AppState结构中。

该应用程序有 2 个线程:

  1. 主线程循环将内容绘制到屏幕上。它需要一个不可变的引用来AppState进行绘图。
  2. 偶尔会产生第二个线程来执行一些 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和频道的信息,但我没有足够的经验来拨打电话。希望得到一些指导(任何指向教程/文档的链接都非常受欢迎)。

标签: multithreadingrust

解决方案


推荐阅读