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锁之间的睡眠功能,但在两者之间有睡眠功能,而这个程序从来没有遇到死锁!只是在我将其更改为此之后,有时会开始陷入僵局。
如果在两个
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();
}
}
如果没有这样的睡眠,很可能至少有一位哲学家会赢得比赛,并能够在另一个哲学家阻止他之前拿起两把叉子。在那之后,至少这位哲学家会尝试在他的邻居思考的时候吃饭,并在他们吃饭的时候睡觉,这意味着没有真正的理由造成僵局。