iOS-GCD-DispatchQueue, WorkItem and Deadlock基本介紹

Gordon Feng
程式愛好者
Published in
5 min readJan 28, 2022
Dead lock is like two guys refuse to wake up until the other guy wake up first.

除了上一篇所講到DispatchQueue.main, DispatchQueue.global外,這篇我們將介紹:

  1. 客製化一個DispatchQueue
  2. 介紹DispatchWorkItem
  3. DeadLock

客製化一個DispatchQueue

還有另一個做法是不使用DispatchQueue.global(),就是自己實作一個DispatchQueue.init如下

DispatchQueue Label為該Queue的唯一值,當我們使用一些Debug工具例如Instruments、 sample、 stackshots 或 crash reports,就可以用來辨認是哪一個Queue所執行,但因為所有framework或library都有可能創造自己的DispatchQueue,因此官方建議使用反轉的Domain name來保證此Label在App是唯一值。

自己實作一個DispatchQueue另外一個需要注意到的是,實做出來的DispatchQueue預設是同步執行的,任務會跑在當前的執行緒,若當前的執行緒為主執行緒,則任務會執行在主執行緒上。而上一篇介紹的DispatchQueue.global()預設是非同步,若要將自己實作出來的Queue改成非同步,讓任務在背景執行緒下執行,則必須要加上attributes: .concurrent。

但必須注意的是,額外創建的DispatchQueue,都會佔系統資源,若創建太多的DispatchQueue,可能會造成資源耗盡,因此若可以,盡量使用DispatchQueue.global(),避免消耗過多的資源。

DispatchWorkItem

簡單來說DispatchWorkItem就是一個你可以設定qos,並提供flag調整不同行為,且可以取消執行的closure。

Task 0 start
Task 1 start
Task 2 start
Task 3 start
Task 4 start
Task 5 start
Task 6 start
Task 7 start
Task 8 start
Task 9 start
Task 9 completed
Task 10 start
---Start cancel workItem---
Task 2 is Cancelled
Task 0 is Cancelled
Task 1 is Cancelled
Task 3 is Cancelled
Task 5 completed
Task 6 is Cancelled
Task 7 is Cancelled
Task 8 completed
Task 10 is Cancelled
Task 4 completed

我們在範例中,我們在for 迴圈內創建了0–10的WorkItem,在裏面模擬Task進行,且在之中安插了檢查是否被Cancel的機制,若被Cancel則印出已被取消並return。

需要澄清的是,WorkItem.cancel()本身並不會影響已經執行的Task,被標示Cancel的workItem就算被送給Queue也不會被執行到。

Task 0 start
Task 1 start
Task 2 start
Task 3 start
Task 4 start
---Start cancel workItem---
Task 3 completed
Task 0 completed
Task 2 completed
Task 1 completed
Task 4 completed

另外一種應用是透過DispatchWorkItem.notify安排順序,從下面的Code我們可以等待拿到資料後,在主執行緒上更新畫面。

Fetch Data begin...
Fetch Data completed!
Update UI please.

Deadlock

是一個當兩個任務互相阻擋彼此執行的狀況。

發生Deadlock的狀況有很多種,其中一種狀況是,若當前為同步 Queue正在運行下,又發送需同步執行的任務給同一個Queue,就會發生Deadlock:

Deadlock example

上述例子中,我們創造一個同步Queue(serialQueue),並送出第一個任務,這個任務內容是呼叫同一個serialQueue以同步的方式執行第二個任務,在同步執行下,任務2(Second task)需等待任務1(First task)結束後才能開始執行,而任務1要完成的必要條件就是任務2完成後,任務1才能結束,因此,在任務1與任務2互相等待的情況下,兩個任務會互相卡死無法執行,而導致Deadlock。

--

--