Skip to content

Commit e2ecf27

Browse files
committed
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.
1 parent 3e268f2 commit e2ecf27

File tree

1 file changed

+10
-3
lines changed

1 file changed

+10
-3
lines changed

src/doc/trpl/dining-philosophers.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ impl Philosopher {
512512

513513
fn eat(&self, table: &Table) {
514514
let _left = table.forks[self.left].lock().unwrap();
515+
thread::sleep_ms(150);
515516
let _right = table.forks[self.right].lock().unwrap();
516517

517518
println!("{} is eating.", self.name);
@@ -597,6 +598,7 @@ We now need to construct those `left` and `right` values, so we add them to
597598
```rust,ignore
598599
fn eat(&self, table: &Table) {
599600
let _left = table.forks[self.left].lock().unwrap();
601+
thread::sleep_ms(150);
600602
let _right = table.forks[self.right].lock().unwrap();
601603
602604
println!("{} is eating.", self.name);
@@ -607,11 +609,14 @@ fn eat(&self, table: &Table) {
607609
}
608610
```
609611

610-
We have two new lines. We’ve also added an argument, `table`. We access the
612+
We have three new lines. We’ve added an argument, `table`. We access the
611613
`Table`’s list of forks, and then use `self.left` and `self.right` to access
612614
the fork at that particular index. That gives us access to the `Mutex` at that
613615
index, and we call `lock()` on it. If the mutex is currently being accessed by
614-
someone else, we’ll block until it becomes available.
616+
someone else, we’ll block until it becomes available. We have also a call to
617+
`thread::sleep_ms` between the moment first fork is picked and the moment the
618+
second forked is picked, as the process of picking up the fork is not
619+
immediate.
615620

616621
The call to `lock()` might fail, and if it does, we want to crash. In this
617622
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
660665
you look at the pattern, it’s all consistent until the very end. Monsieur
661666
Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what
662667
prevents deadlock, actually: one of our philosophers is left handed! This is
663-
one way to solve the problem, and in my opinion, it’s the simplest.
668+
one way to solve the problem, and in my opinion, it’s the simplest. If you
669+
change the order of the parameters, you will be able to observe the deadlock
670+
taking place.
664671

665672
```rust,ignore
666673
let handles: Vec<_> = philosophers.into_iter().map(|p| {

0 commit comments

Comments
 (0)