iOS| #28 | GCD 筆記 part3. DispatchSemaphore

iOS| #28 part2.提到了DispatchGroup的使用,這次會說明另一個相似的物件,叫做DispatchSemaphore。

Tommy
Apr 25, 2022
Photo by Markus Spiske on Unsplash

DispatchSemaphore的功能與DispatchGroup相當類似,但Semaphore可以利用參數value控制資源的運用(例如:同時只能執行2個任務)。

名詞解釋

在正式講解前有一些DispatchSemaphore的method可能要先熟悉一下

  • signal
    Semaphore計數增加
  • wait
    Semaphore計數減少

程式範例

官方文件說明主要會有兩種做法:

  1. 預設value為0,當執行任務時會呼叫wait,使其value -1(變成負數)。這時候執行緒會block住,直到呼叫signal,使其value +1(變回零),這時候才會繼續執行後續的任務。
  2. 預設value為任一正整數,目的是為了管理同時可以運作的執行緒數量。

以下就讓我們看看範例:

  1. 首先建立一個project,實作func dispatchSemaphoreTest()。
  2. 在viewDidLoad()呼叫此func 。

3. 生成DispatchSemaphore、DispatchQueue之後測試方便使用。

接下來會用程式範例在func dispatchSemaphoreTest()中 print出一些東西來觀察利用DispatchSemaphore執行任務時的狀況

  • 預設value為0
    任務會按照順序完成,與iOS| #28 part2.提到的DispatchGroup使用wait的結果一樣

結果如下:

開門洗手吃飯
  • 預設value為5
    同時最多只能執行5個任務。依照Semaphore的特性,value為負的話執行緒會被block住,直到value≥0。

這邊的範例稍微多了幾個步驟:

  1. 宣告屬性count負責記錄現在有幾項任務

2. 實作func countValue()
當做完五項任務時會print出訊息,並將計數器歸零

//控制counterfunc countValue(){  count += 1  if count == 5 {   print("已完成五項任務")   count = 0  }}

3. 實作func dispatchSemaphoreTest()範例內容

補充:在func dispatchSemaphoreTest()中會使用asyncAfter & sleep(1)是為了讓gif結果看起來更明顯,因為任務非常簡單,要避免程式一下子就做完所有事。

結果如下:

補充:
在使用上會有一些要注意的地方,經過測試後將這些情境列在下方

  • 使用呼叫wait()使value為負數的話,會讓程式碼停在wait()這邊,在此以後的其他任務會暫時不會被執行。

透過以下的執行結果可以觀察程式碼34行的print(“完成”)並沒有馬上被執行。因為使用Semaphore的緣故等到三秒後執行完signal()使value≥0才會繼續執行。

  • 若value為負數的話,一直沒有呼叫signal()。執行緒會永遠block住,無法執行任何動作。

若內容有誤煩請指教,感謝收看。

--

--