From e2ecf279b6795d0a86a964fdc7a31c1f3981456f Mon Sep 17 00:00:00 2001 From: "Irving A.J. Rivas Z." Date: Mon, 19 Oct 2015 10:02:46 -0400 Subject: [PATCH] Made the example capable of consistent deadlocking To augment the didactic effect, made placed the thread::sleep_ms call in the last example, so that there will be time for the other locks to happen; without this, I was unable to observe the deadlock in over 1,000 runs when there was no left-handed philosopher. --- src/doc/trpl/dining-philosophers.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/dining-philosophers.md b/src/doc/trpl/dining-philosophers.md index 28702d95b60a..e81ae4648ad4 100644 --- a/src/doc/trpl/dining-philosophers.md +++ b/src/doc/trpl/dining-philosophers.md @@ -512,6 +512,7 @@ impl Philosopher { fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); + thread::sleep_ms(150); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); @@ -597,6 +598,7 @@ We now need to construct those `left` and `right` values, so we add them to ```rust,ignore fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); + thread::sleep_ms(150); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); @@ -607,11 +609,14 @@ fn eat(&self, table: &Table) { } ``` -We have two new lines. We’ve also added an argument, `table`. We access the +We have three new lines. We’ve added an argument, `table`. We access the `Table`’s list of forks, and then use `self.left` and `self.right` to access the fork at that particular index. That gives us access to the `Mutex` at that index, and we call `lock()` on it. If the mutex is currently being accessed by -someone else, we’ll block until it becomes available. +someone else, we’ll block until it becomes available. We have also a call to +`thread::sleep_ms` between the moment first fork is picked and the moment the +second forked is picked, as the process of picking up the fork is not +immediate. The call to `lock()` might fail, and if it does, we want to crash. In this case, the error that could happen is that the mutex is [‘poisoned’][poison], @@ -660,7 +665,9 @@ We need to pass in our `left` and `right` values to the constructors for our you look at the pattern, it’s all consistent until the very end. Monsieur Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what prevents deadlock, actually: one of our philosophers is left handed! This is -one way to solve the problem, and in my opinion, it’s the simplest. +one way to solve the problem, and in my opinion, it’s the simplest. If you +change the order of the parameters, you will be able to observe the deadlock +taking place. ```rust,ignore let handles: Vec<_> = philosophers.into_iter().map(|p| {