From 5d0e95ca2825ce52c9ebf07eb43b2e30772ab01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Thu, 3 Oct 2024 16:29:10 +0100 Subject: [PATCH] [docs/advanced] Fix tables in deadlock.md --- docs/advanced/deadlock.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/advanced/deadlock.md b/docs/advanced/deadlock.md index b878ccb85..f1bab5bdb 100644 --- a/docs/advanced/deadlock.md +++ b/docs/advanced/deadlock.md @@ -17,13 +17,13 @@ A deadlock can occur when more than one thread attempts to lock more than one mutex, and two of the threads lock two of the mutexes in different orders. For example, consider mutexes `mu1` and `mu2`, and threads T1 and T2, executing: - | T1 | T2 ---- | ------------------- | ------------------- -1 | `mu1.lock()`{.good} | `mu2.lock()`{.good} -2 | `mu2.lock()`{.bad} | `mu1.lock()`{.bad} -3 | `/* work */` | `/* work */` -4 | `mu2.unlock()` | `mu1.unlock()` -5 | `mu1.unlock()` | `mu2.unlock()` +| | T1 | T2 | +|--- | ------------------- | -------------------| +|1 | `mu1.lock()`{.good} | `mu2.lock()`{.good}| +|2 | `mu2.lock()`{.bad} | `mu1.lock()`{.bad} | +|3 | `/* work */` | `/* work */` | +|4 | `mu2.unlock()` | `mu1.unlock()` | +|5 | `mu1.unlock()` | `mu2.unlock()` | Now if T1 manages to lock `mu1` and T2 manages to lock `mu2` (as indicated in green), then both threads will block while trying to lock the respective other @@ -37,17 +37,17 @@ point; what matters is only the order of any attempt to *lock* the mutexes. For example, the following, more complex series of operations is just as prone to deadlock: - | T1 | T2 ---- | ------------------- | ------------------- -1 | `mu1.lock()`{.good} | `mu1.lock()`{.good} -2 | waiting for T2 | `mu2.lock()`{.good} -3 | waiting for T2 | `/* work */` -3 | waiting for T2 | `mu1.unlock()` -3 | `mu2.lock()`{.bad} | `/* work */` -3 | `/* work */` | `mu1.lock()`{.bad} -3 | `/* work */` | `/* work */` -4 | `mu2.unlock()` | `mu1.unlock()` -5 | `mu1.unlock()` | `mu2.unlock()` +| | T1 | T2 | +|--- | ------------------- | -------------------| +|1 | `mu1.lock()`{.good} | `mu1.lock()`{.good}| +|2 | waiting for T2 | `mu2.lock()`{.good}| +|3 | waiting for T2 | `/* work */` | +|3 | waiting for T2 | `mu1.unlock()` | +|3 | `mu2.lock()`{.bad} | `/* work */` | +|3 | `/* work */` | `mu1.lock()`{.bad} | +|3 | `/* work */` | `/* work */` | +|4 | `mu2.unlock()` | `mu1.unlock()` | +|5 | `mu1.unlock()` | `mu2.unlock()` | When the mutexes involved in a locking sequence are known at compile-time, then avoiding deadlocks is “merely” a matter of arranging the lock