diff options
| author | Irving A.J. Rivas Z. <axel.rivas@gmail.com> | 2015-10-19 10:02:46 -0400 |
|---|---|---|
| committer | Irving A.J. Rivas Z. <axel.rivas@gmail.com> | 2015-10-19 10:02:46 -0400 |
| commit | e2ecf279b6795d0a86a964fdc7a31c1f3981456f (patch) | |
| tree | ae5fd23ca2acbd29a182143cd7cd5d7ab2673577 | |
| parent | 3e268f2fbafca7e0a59bf77e17985a27c61d5a11 (diff) | |
| download | rust-e2ecf279b6795d0a86a964fdc7a31c1f3981456f.tar.gz rust-e2ecf279b6795d0a86a964fdc7a31c1f3981456f.zip | |
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.
| -rw-r--r-- | src/doc/trpl/dining-philosophers.md | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/src/doc/trpl/dining-philosophers.md b/src/doc/trpl/dining-philosophers.md index 28702d95b60..e81ae4648ad 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| { |
