---
# System prepended metadata

title: OS-Deadlock-複習
tags: [NCNU]

---

# What is deadlock?

在一個 task 想要向 OS 索取 resource (資源) 的時候，如果這些 resource 並非能夠馬上使用的，就會使這個 task 進入 wait (等待) 的狀態，如果這些 resource 又被其他正在 wait 的 task 所持有，將會使這個正在 wait 的 task 永遠無法改變其 wait 的狀態，這個現象就是 **deadlock (死結)**

> 這邊的 task 指的是一個抽象的執行單位，可能是 process 或是 thread，姜媽的講義似乎都以 thread 表示

:::info
對死結的最佳說明要回溯到美國堪薩斯州在 20 世紀初所制定的一條法律來詮釋，部分內容為: 當兩輛火車同時到達一交叉路口時，雙方都必須完全停止，待一輛駛去之後，另一輛再通過
:::

# 系統模型

一個 OS 包含可分配給 task 的**有限** resource。這些 resource 可區分成許多 class (類型)，每種都會含有一至數個相同類型的 instance (實例)

一個 task 在使用一 resource 前必須先進行 **request (請求)**，並在使用完後 **release (釋放)**

在正常運作模式下，一個 task 都只能依下方順序去使用資源:

1. request

> 若此請求無法馬上被認可，例如這個 resource 正在被使用，則 task 進入 wait 的狀態等待此 resource

2. use

> task 得以使用此 resource

3. release

> task 釋放此 resource，告知 OS 這個 resource 變回可用的狀態

:::info
例如在撰寫 C 程式時，使用 `malloc()` 去 request 一塊動態的記憶體空間跟使用完後使用 `free()` release 這一段記憶體空間
:::

:::warning
一個 task 所要求的 resource 不可超過 OS 可用的 resource 總數
:::

# 範例: mutex (互斥鎖) 的 deadlock

以下程式碼範例初始化了倆 mutex

```c
pthread_mutex_t first_mutex;
pthread_mutex_t second_mutex;

pthread_mutex_init(&first_mutex, NULL);
pthread_mutex_init(&second_mutex, NULL);
```

接下來，產生 `thread_one` 跟 `thread_two` 分別執行 `do_work_one()` 跟 `do_work_two()` 兩個 function

```c
/* thread one runs in this function */
void *do_work_one(void *param) {
    pthread_mutex_lock(&first_mutex);
    pthread_mutex_lock(&second_mutex);
    /** * Do some work */
    pthread_mutex_unlock(&second_mutex);
    pthread_mutex_unlock(&first_mutex);
    pthread_exit(0);
}

/* thread two runs in this function */
void *do_work_two(void *param) {
    pthread_mutex_lock(&second_mutex);
    pthread_mutex_lock(&first_mutex);
    /** * Do some work */
    pthread_mutex_unlock(&first_mutex);
    pthread_mutex_unlock(&second_mutex);
    pthread_exit(0);
}
```

`thread_one` 嘗試以

1. `first_mutex`
2. `second_mutex`

取得 mutex

`thread_two` 嘗試以

1. `second_mutex`
2. `first_mutex`

取得 mutex

當 `thread_two` 獲得 `second_mutex` 時，若 `thread_one` 獲得 `first_mutex`，則**有可能造成 deadlock**

# 造成 deadlock 的四個"必要"條件

> 全部**同時成立**，才會造成 deadlock

## Mutual exclusion 互斥

一次只能有一 task 使用此 resource，意即 Non-shareable (不可共享的)

## Hold and Wait 佔用與等待

存在一已 hold (佔用) resource 的 task，且正在 wait 被其他 task 佔用的 resource

## No Preemption 不可搶先

resource 無法被 preemption (搶先)，意即這個 resource 只能被 hold 的 task 去 release

## Circular wait 循環等待

存在一等待彼此的 task 集合，假設有 {A, B, C} 三個 tasks，A 等 B，B 等 C，C 等 A，形成迴圈就是 circular wait

:::info
四個條件事實上息息相關，像

- 處於 circular wait 的狀態時，也包含了 hold and wait
- 又或是 task 0 在等待 task 1 時，若 task 0 能夠搶奪 task 1 的資源，就不會發生等待，所以一定也有 no preemtion 這個條件
:::

# Resource-Allocation Graph (資源分配圖)

deadlock 現象可用 system resource-allocation graph (系統資源配置圖) 表示

- 由一組 vertices (頂點) V 和一組 edges (邊) E 組成
- V 又具有兩種類型
    - T 表示正在執行之 task 集合，$T = \{ T_1, T_2, ..., T_n \}$
    - R 表示 OS 所有 resource class 的集合，$R = \{R_1, R_2, ..., R_n\}$
- E 也有兩種
    - request edge (請求邊)，由 T 指向 R，意即 task T 已要求 class R 的 resource instance，且正在 wait，通常這樣表示 $T_i \rightarrow R_i$
    - assignment edge (分配邊)，由 R 指向 T，意即 class R 的某個 resource instance 已被 task T 持有，處於 hold 的狀態，通常這樣表示 $R_i \rightarrow T_i$

## 例圖

![Untitled Diagram](https://hackmd.io/_uploads/BJBRRA2Lp.png)

- 集合 $T$ $R$ $E$
    - $T = \{T_1, T_2, T_3\}$
    - $R = \{R_1, R_2, R_3, R_4\}$
    - $E = \{T_1 \rightarrow R_1 , T_2 \rightarrow R_3, R_1 \rightarrow T_2, R_2 \rightarrow T_2, R_2 \rightarrow T_1, R_3 \rightarrow T_3\}$
- resource instance (黑點點)
    - class $R_1$ 的 resource 有 1 個 instance
    - class $R_2$ 的 resource 有 2 個 instance
    - class $R_3$ 的 resource 有 1 個 instance
    - class $R_4$ 的 resource 有 3 個 instance
- task 狀態
    - $T_1$ 正在 hold $R_2$ 的一個 instance，並在等待一個 $R_1$ 的 instance
    - $T_2$ 正在 hold $R_1$ 以及 $R_2$ 的各一個 instance，並在等待一個 $R_3$ 的 instance
    - $T_3$ 正在 hold $R_3$ 的一個 instance

:::info
- 如果此圖中沒有 cycle (循環) 存在，則此系統中不會發生 deadlock
- 若此圖中具有 cycle 且所有 class 的 resource 都只有一個 instance 就會發生 deadlock
- 若此圖中具有 cycle 且所有 class 的 resource 有多個 instance 則**有可能** (不一定) 發生 deadlock
:::

# 處理 deadlock 的方式

一般來說，可以從以下三種方法之一來處理 deadlock:

- 使用某種 protocol (協議) 以**預防**或是**防止** deadlock
    - deadlock prevention
    - deadlock avoidance
- 允許系統進入 deadlock 的狀態，**偵測**到後再想辦法**恢復**
    - deadlock detection
    - deadlock recovery
- ignore (忽視) deadlock，假裝系統從沒發生 deadlock

:::info
第三種方法被大部分的 OS 所採用，包含 UNIX-like 以及 Windows，因此處理 deadlock 通常由系統程式開發人員自行處理
:::

# Deadlock prevention (預防)

提供一組方法，確保之前提及的四個產生 deadlock 的必要條件，至少有一項不被滿足，以下分別進行說明

## Mutual exclusion

若 mutual exclusion 成立，則代表至少有一項 resource 是不可共享的，反之，可共享的 resource 就不必以 mutex 的方式進行存取，所以就不會產生 deadlock

假設有很多 task 都想要開啟一個 read-only (唯讀) 的檔案，則可以讓它們同時存取此檔案

:::info
但實務上來說，幾乎不可能透過排除 mutual exclusion 來預防 deadlock，因為許多 resource **本質上就是無法共用**的
:::

## Hold and Wait

為了使此條件不成立，需要保證一個 task 在 request 一項 resource 時，不可 hold 其他 resource，以下介紹兩種方式

- 每個 task 在執行前，都必須先 request 並被 OS 成功分配所需的 resource
- 只允許 task 在未 hold 任何 resource 的情況下才能夠 request resource，意即一個 task 在需要某些 resource 時，在進行 request 前必須先 release 掉所有正 hold 的 resource

這邊假設有一 task，要從 DVD 複製資料至一 disk file，然後對其進行排序，最後將結果由印表機印出

如果使用第一種方法，此 task 就必須一開始就 request DVD、disk file 跟印表機，雖在最後才使用到印表機，但這個 task 整個執行過程中都 hold 著印表機

第二種方法允許這個 task 一開始只 request DVD 跟 disk file，等此 task 將 DVD 的資料複製完畢後，就要把 DVD 跟 disk file 都 release 掉，然後再要求 disk file 跟印表機，待列印完成後再 release 掉這兩項 resource

:::info
這兩種方式有兩個主要的缺點:

- 資源使用率 (resource utilization) 有可能很低，因為大部分時間許多 resource 可能只是被分配而未實際使用
- 有可能產生 starvation (飢餓) 現象，當一個 task 需要用到的許多 resource，其中一樣被其他 task 使用，這個 task 將會永遠處於 wait 狀態
:::

## No Preemption

要避免此條件，有以下幾種方法:

- 如果某 task 已經 hold 著一些 resource，而它要 request 一個無法立即獲得的 resource (也就是它會處於 wait 的狀態)，則此 task hold 的 resource 應該要給其他 task 搶先使用，意即處於 wait 狀態後會 implicitly (隱含地) release 所有 resource
- 如果某 task 需要幾項 resource，須先檢查 resource 是否可被使用，如果可以就直接分配，如果不是，就再往下檢查說這些 resource 是否被一些其他正在 wait 的 task hold 著，如果是的話就從這些正在 wait 的 task 把 resource 搶先分配給此 task，如果真的無法立即分配此 task 就會進入 wait 的狀態，同理它原本 hold 的 resource 就能夠被其他 task 搶先

> 上方提及的方式，被搶先或者處於 wait 的 task，只有能夠重新獲得原本 hold 的 resource 再加上正 request 的 resource 時，才會繼續執行

:::info
此些做法，通常適用於 resource 的狀態能夠輕易被保存及恢復的情況下，像是 memory 以及 CPU register，不適用於 mutex 或是 semaphore 這類的 resource
:::

## Circular wait

確保不會發生此條件的方法是: 對所有 resource class 強迫安排一線性的順序，task 在 request resource 時必須依照數字大小，遞增的提出 request

為了方便說明，假設 $R = \{R_1, R_2, R_3, ..., R_m\}$ 為 resource class 的集合，然後定義一函數 $F: R \rightarrow N$ 來產生一對一的正整數，舉例來說，若 resource class 集合 $R$ 中有包含 DVD drive、disk drive 還有印表機則可能表示如下

- $F(DVD) = 1$
- $F(disk) = 5$
- $F(printer) = 12$

然後接下來可以考慮以下做法來預防 deadlock:

- 每一 task 只能依遞增的方式去 request resource，以上方的例子來說，若有一 task 需要同時使用 DVD 跟印表機，則必須先要求 DVD 才能再要求印表機 (因為 $F(printer)$ > $F(DVD)$)
- 若一 task 要求 resource class $R_j$ 時，並定要先 release 所有的資源 $R_i$，其中 $R_j \ge R_i$

:::info
上方提及的預防 deadlock 的方式，都會有一些副作用，就是

- low device utilization (降低資源使用率)
- reduced system throughput (降低系統效能)
:::

# Deadlock avoidance (避免)

避免 deadlock 主要的概念就是，要讓 task 提供多一些關於 request resource 的相關資訊，其中最簡單的且最有用的方式就是，每個 task 都需要宣告其所需每種 class 的 resource 之最大數量

使用這類資訊就能建立出一演算法去保證系統不會進入 deadlock ，這種演算法會動態檢查 resource-allocation state (資源分配狀態)，以確保不會出現 circular wait

:::info
resource-allocation state 會被三個元素決定:

- available (可被使用的) resources 數量
- allocated (已分配的) resources 數量
- task 對 resource 的 maximum demands (最大需求)
:::

## safe state (安全狀態)

如果 OS 能以某種順序將 resource 分配給各個 task (符合其最大值)，且不會產生 deadlock，就稱為 safe state

或者說一個 OS 只有在 safe sequence 存在時，才算處於 safe state

> safe sequence 是指一群 task 的執行順序，此順序能夠使這些 task 能夠在不產生 deadlock 的情況下順利執行完畢

:::info
- 如果 OS 處於 safe state 則**不會**發生 deadlock
- 如果 OS 處於 unsafe state 則**有可能**發生 deadlock
- deadlock avoidance 的主要方式就是確保 OS 永遠不會進入 unsafe state
:::

## Resource-Allocation Graph Algorithm

如果有一 resource 分配系統，其中所有 resource class 都各**只有一個 instance**，則之前提及的 resource-allocation graph 可用來避免 deadlock

這邊要再額外加上一個新的 claim edge (申請邊)，此種邊與 request edge 相似，都是由 T 指向 R，但以**虛線**表示，意義是 T 有可能會需要 R，當 T request R 時，要將 claim edge 轉為 request edge，然後在 T release R 時，要將 assignment edge 再轉回 claim edge

### 例圖

![Untitled Diagram](https://hackmd.io/_uploads/H1sPSi6L6.png)

這邊假設 $T_2$ 想要 request $R_2$，雖然此時 $R_2$ 可用，但不能將 $R_2$ 分配給 $T_2$，因為將會在圖中產生 cycle，而系統就會處於 unsafe state，這時如果 $T_1$ request $R_2$ 且 $T_2$ 要求 $R_1$ 就會產生 deadlock

:::info
- resource-allocation graph algorithm 不適用於有多個 instance 的 resource 分配系統
- 使用 cycle detection 去判斷系統是否處於 safe state
:::

## Banker's Algorithm

- 如果是在所有 resource class 有很多 instance 的狀況，banker's algorithm 就會是個較好的選擇
- 當一新的 task 進入系統時，必須先宣告可能需要的每種 resource class 的最大數量，此數量不能超過系統所有資源的總數
- 當一 task request 一組 resource 時，就要馬上評估是否會因此進入 unsafe state，若仍能處於 safe state，就能將這些 resource 分配給此 task，否則此 task 就必須 wait 直到其他 task release 足夠的 resource

:::info
此名稱是出自銀行系統中，確保可用資金都能滿足客戶需求的分配方式
:::

### 例題

- 有 5 個 task
    - $T_0$
    - $T_1$
    - $T_2$
    - $T_3$
    - $T_4$
- 有 3 種 resource class
    - A (10 個 instance)
    - B (5 個 instance)
    - C (7 個 instance)

目前的狀態如下

- Allocation (已分配的 resource)

|       |  A  |  B  |  C  |
|:-----:|:---:|:---:|:---:|
| $T_0$ |  0  |  1  |  0  |
| $T_1$ |  2  |  0  |  0  |
| $T_2$ |  3  |  0  |  2  |
| $T_3$ |  2  |  1  |  1  |
| $T_4$ |  0  |  0  |  2  |

- Max (最大需求)

|       |  A  |  B  |  C  |
|:-----:|:---:|:---:|:---:|
| $T_0$ |  7  |  5  |  3  |
| $T_1$ |  3  |  2  |  2  |
| $T_2$ |  9  |  0  |  2  |
| $T_3$ |  2  |  2  |  2  |
| $T_4$ |  4  |  3  |  3  |

試求出 safe sequence

### 解法

1. 先求出 Available

```
A 可從題目中條件知道有 10 個 instance
所以去剪掉 Allocation 中已被分配出去的部分即可得出:

A = 10 - (0 + 2 + 3 + 2 + 0) = 3

B, C 同理

B = 5 - (1 + 0 + 0 + 1 + 0) = 3

C = 7 - (0 + 0 + 2 + 1 + 2) = 2
```

- Available (可用資源)

|  A  |  B  |  C  |
|:---:|:---:|:---:|
|  3  |  3  |  2  |

2. 再求出 Need

```
求出 Need 的公式為 Max - Allocation

T0 = (7, 5, 3) - (0, 1, 0) = (7, 4, 3)
T1 = (3, 2, 2) - (2, 0, 0) = (1, 2, 2)
T2 = (9, 0, 2) - (3, 0, 2) = (6, 0, 0)
T3 = (2, 2, 2) - (2, 1, 1) = (0, 1, 1)
T4 = (4, 3, 3) - (0, 0, 2) = (4, 3, 1)
```

- Need

|       |  A  |  B  |  C  |
|:-----:|:---:|:---:|:---:|
| $T_0$ |  7  |  4  |  3  |
| $T_1$ |  1  |  2  |  2  |
| $T_2$ |  6  |  0  |  0  |
| $T_3$ |  0  |  1  |  1  |
| $T_4$ |  4  |  3  |  1  |

3. 判定目前是否有 safe sequence

```
目前已知 Available =  (3, 3, 2)
檢查看看目前 T0 ~ T4 的 Need 當中是否有可以被成功分配的 (就是要 <= (3, 3, 2))

1. T1 (1, 2, 2) <= (3, 3, 2)
2. 成功執行後釋放資源 Available (3, 3, 2) 從 T1 獲得 Allocation (2, 0, 0)
3. 所以 Available 變為 (3, 3, 2) + (2, 0, 0) = (5, 3, 2)
4. 重新開始找尋剩下的 task 中是否有可以成功分配的

最終可得 T1, T3, T4, T2, T0 這個 safe sequence
```

### 如果原始狀態中，$T_1$ 額外 request (1, 0, 2) 的 resource 呢?

1. 首先先檢查 (1, 0, 2) 有沒有超過 Need 且 Available 夠用

```
原始狀態中 T1 的 Need = (1, 2, 2)，(1, 0, 2) <= (1, 2, 2) 所以條件成立
原始狀態中 Available = (3, 3, 2)，(1, 0, 2) <= (3, 3, 2) 所以能夠分配
```

2. 狀態改變

```
因應這額外的分配，需要調整相應的狀態
Available = (3, 3, 2) - (1, 0, 2) = (2, 3, 0)
T1 的 Allocation = (2, 0, 0) + (1, 0, 2) = (3, 0, 2)
T1 的 Need = (3, 2, 2) - (3, 0, 2) = (0, 2, 0)
```

得出狀態如下

- Allocation (已分配的 resource)

|       |  A  |  B  |  C  |
|:-----:|:---:|:---:|:---:|
| $T_0$ |  0  |  1  |  0  |
| $T_1$ |  3  |  0  |  2  |
| $T_2$ |  3  |  0  |  2  |
| $T_3$ |  2  |  1  |  1  |
| $T_4$ |  0  |  0  |  2  |

- Need

|       |  A  |  B  |  C  |
|:-----:|:---:|:---:|:---:|
| $T_0$ |  7  |  4  |  3  |
| $T_1$ |  0  |  2  |  0  |
| $T_2$ |  6  |  0  |  0  |
| $T_3$ |  0  |  1  |  1  |
| $T_4$ |  4  |  3  |  1  |

- Available (可用資源)

|  A  |  B  |  C  |
|:---:|:---:|:---:|
|  2  |  3  |  0  |

3. 判定目前是否有 safe sequence

```
參考上方做法，可得出 safe sequence: T1, T3, T4, T0, T2
```

所以這個 request 是可行的

:::info
- 在此新狀態中，若 $T_4$ 想要再額外 request (3, 3, 0) 就是不可行的，因為 Available 已經不夠用了
- 但在此新狀態中，$T_0$ 再額外 request (0, 2, 0)，就算 Available 夠用也不能答應，因為會找不到 safe sequence，意即進入 unsafe state
:::

# Deadlock detection (偵測)

假設 OS 沒有 deadlock prevention 跟 deadlock avoidance 的機制，此時系統就須提供

- 檢察系統狀態判斷是否有 deadlock 產生的演算法
- 從 deadlock 恢復的機制

## Wait-for Graph

- 適用於所有 resource class 都各**只有一個 instance** 的系統
- 同樣變化自 resource-allocation graph
- 也同樣是判斷是否有 cycle 的存在
- 簡單來說就是拿掉所有 resource 並把等待的邊連起來

假設有一 resource-allocation graph 如下

![Untitled Diagram](https://hackmd.io/_uploads/HkMnRATUa.png)

則 wait-for graph 如下

![Untitled Diagram](https://hackmd.io/_uploads/BJpSyyCLT.png)

:::info
- 若 wait-for graph 中有 cycle，則系統必有 deadlock
- 為了偵測 deadlock，系統必須一直維護此圖
:::

## Deadlock Detection Algorithm

- 適用於所有 resource class 都**有多個 instance** 的系統

### 例題

- 有 5 個 task
    - $T_0$
    - $T_1$
    - $T_2$
    - $T_3$
    - $T_4$
- 有 3 種 resource class
    - A (7 個 instance)
    - B (2 個 instance)
    - C (13 個 instance)

目前的狀態如下

- Allocation

|       |  A  |  B  |  C  |
|:-----:|:---:|:---:|:---:|
| $T_0$ |  0  |  1  |  0  |
| $T_1$ |  2  |  0  |  0  |
| $T_2$ |  3  |  0  |  3  |
| $T_3$ |  2  |  1  |  1  |
| $T_4$ |  0  |  0  |  2  |

- Request

|       |  A  |  B  |  C  |
|:-----:|:---:|:---:|:---:|
| $T_0$ |  0  |  0  |  0  |
| $T_1$ |  2  |  0  |  2  |
| $T_2$ |  0  |  0  |  0  |
| $T_3$ |  1  |  0  |  0  |
| $T_4$ |  0  |  0  |  2  |

- Available

|  A  |  B  |  C  |
|:---:|:---:|:---:|
|  0  |  0  |  0  |

1. 找尋 safe sequence

```
1. 看看 Available (0, 0, 0) 能否執行任何一個 task
2. T0 的 Request (0, 0, 0) <= Avaiable (0, 0, 0)，可以執行
3. T0 release resource 給 Available (0, 0, 0) + (0, 1, 0) = (0, 1, 0)
4. 看看 Available (0, 1, 0) 能否執行任何一個剩下的 task，並依此類推

最終可得 T0, T2, T3, T1, T4
```
:::info
- 假設在初始狀態，$T_2$ 額外進行請求 (0, 0, 1)，將會導致 deadlock 發生，因為沒有足夠的 resource 進行任何 task
:::

### Detection-Algorithm 的使用

需要考慮下方兩種因素，去判斷什麼時候該使用 detection-algorithm

- 多久會發生一次 deadlock
- 有多少個 task 被 deadlock 影響

若經常發生 deadlock，則演算法的執行將會變得頻繁，但在解決 deadlock 前，系統又會不斷地把 resource 分配給 task，因此受到 deadlock 影響的 task 可能會越來越多

# Recovery (恢復) from deadlock

當偵測到 deadlock 之後，可以有兩種結束 deadlock 的方式

- 直接終止一或多個 task
- 搶先一或多個陷入 deadlock 的 task 所持有的 resource

## 終止 task

藉由中止 task 來消除 deadlock 有兩種方法

- 直接終止所有在 deadlock 中的 task
    - 雖然這樣可以消除 deadlock，但代價會很大，因為這些 task 有可能已經執行了很長時間，而這些計算結果將會被拋棄，並且極有可能要重新計算
- 一次終止一個 task 直到 deadlock 消失
    - 這樣會有不小的系統開銷，因為在每終止一個 task 之後，都必須重新執行 detection-algorithm 去判斷 deadlock 是否還存在

:::info
如果使用第二種方法，就必須決定要終止哪些 task 來消除 deadlock，但許多元素都可以決定要選擇哪個 task

- task 的優先權
- task 工作了多久? 還需要多少時間?
- task 使用了多少 resource，都是哪些 class
- task 還需要多少 resource，才能夠完成
- 有多少 task 需要被終止
- task 的類型
:::

## 搶先陷入 deadlock 的 resource

為了透過 preemption 來消除 deadlock，需要考慮以下三個議題:

- select a victim (選擇犧牲者)
    - 以最小開銷的方式去做選擇
- rollback (回溯)
    - 因 resource 被搶先，所以 task 已經不能正常執行，要能夠讓被搶先的 task 能夠回溯到某個能正確執行的狀態
- starvation (飢餓問題)
    - 保證 task 不會一直被搶先

---

# 考古題

- **Deadlock prevention** provides a set of methods to ensure that at least one of the necessary conditions cannot hold.
- **Deadlock avoidance** requires that OS be given additional information in advance concerning which resources a thread will request and use during its lifetime.
- **low device utilization** and **reduced system throughput** are possible side effects of Preventing Deadlocks.
- When a thread requests an available resource, system must decide if immediate allocation leaves the system in a **safe state**
- **Circular Wait**, which is one way of deadlock prevention,impose a total ordering of all resource types.
- OS will break **hold and wait** to prevent deadlock,which means that OS will require each thread to request and be allocated all its resources before it begins execution.
- When system has only one instance of each resource type, OS can use **Resource-Allocation Graph Algorithm** to execute deadlock avoidance

![image](https://hackmd.io/_uploads/rkEx9QDIT.png)

> allocation: 已獲得的資源數量
> max: 完成工作所需的最大資源量
> available: 系統目前的可用資源

- 將 max - allocation 得出 need
- 接著看 available 是否可以負擔 need
- 若有某一個 thread 可以負擔，完成後須把 allocation 的數字加回去
