为什么这段 Rust 代码不会遇到死锁?

问题描述 投票:0回答:1
use std::{sync::{Arc, Mutex}, thread, time::Duration};
fn main() {
    let mut forks = Vec::with_capacity(5);
    let mut handles = vec![];
    for _ in 1..=5 {
        forks.push(Arc::new(Mutex::new(0)));
    }

    for i in 0..=4 {
        let left_fork = forks[i].clone();
        let right_fork = forks[(i + 1) % 5].clone();
        let handle = thread::spawn(move || {
            loop {
                println!("philosopher {} is thinking...", i);
                thread::sleep(Duration::from_millis(100));
                let right_fork_guard = right_fork.lock().unwrap();
                println!("philosopher {} picked up right fork", i);
                let left_fork_guard = left_fork.lock().unwrap();
                println!("philosopher {} picked up left fork and starts eating..", i);

                thread::sleep(Duration::from_millis(100));
                
                drop(left_fork_guard);
                println!("philosopher {} put down left fork.", i);
                // thread::sleep(Duration::from_millis(100));
                drop(right_fork_guard);
                println!("philosopher {} put down right fork.", i);
            }
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }
}

我编写这个程序是为了模拟哲学家就餐问题。我没有采取任何措施来避免死锁,但该程序可以正常运行。事实上,它确实时不时会遇到死锁,但有时它只是运行而没有死锁(我等了 5 分钟以上,没有死锁!)。当陷入僵局时,这一定是他们的第一轮吃饭。如果他们成功通过第一轮,他们就不会再陷入困境了。

还有一个奇怪的地方是,在Linux、Mac中会出现死锁,但在WINDOWS和WSL中却不会。 多么奇怪!请帮忙!

起初,我没有“哲学家在思考”和right_fork锁之间的睡眠功能,但在两者之间有睡眠功能,而这个程序从来没有遇到死锁!只是在我将其更改为此之后,有时会开始陷入僵局。

rust concurrency
1个回答
0
投票

如果在两个

lock
调用之间添加睡眠,可能会出现系统性死锁:

use std::{sync::{Arc, Mutex}, thread, time::Duration};
fn main() {
    let mut forks = Vec::with_capacity(5);
    let mut handles = vec![];
    for _ in 1..=5 {
        forks.push(Arc::new(Mutex::new(0)));
    }

    for i in 0..=4 {
        let left_fork = forks[i].clone();
        let right_fork = forks[(i + 1) % 5].clone();
        let handle = thread::spawn(move || {
            loop {
                println!("philosopher {} is thinking...", i);
                thread::sleep(Duration::from_millis(100));
                let right_fork_guard = right_fork.lock().unwrap();
                println!("philosopher {} picked up right fork", i);
                thread::sleep(Duration::from_millis(1));
                let left_fork_guard = left_fork.lock().unwrap();
                println!("philosopher {} picked up left fork and starts eating..", i);

                thread::sleep(Duration::from_millis(100));
                
                drop(left_fork_guard);
                println!("philosopher {} put down left fork.", i);
                // thread::sleep(Duration::from_millis(100));
                drop(right_fork_guard);
                println!("philosopher {} put down right fork.", i);
            }
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }
}

游乐场

如果没有这样的睡眠,很可能至少有一位哲学家会赢得比赛,并能够在另一个哲学家阻止他之前拿起两把叉子。在那之后,至少这位哲学家会尝试在他的邻居思考的时候吃饭,并在他们吃饭的时候睡觉,这意味着没有真正的理由造成僵局。

© www.soinside.com 2019 - 2024. All rights reserved.