大多數的API 都會需要用closure來異步接收回傳的結果,避免網路的等待擋住整個執行緒的處理。
但在一些情境下,我們可能會希望這個執行緒是等待的,我們希望拿到結果後再繼續往下走。
在這樣的情況下,我們可以使用DispatchSemaphore。
DispatchSemaphore是Swift中的一個簡單而有效的等待機制使用工具。在基本概念上,它讓你可以設置一個可以控制執行程序繼續或停止的信號。很適合當你需要執行接下來的作業之前,需要先確保某些準備工作已經先完成。
創建一個Semaphore對象
使用DispatchSemaphore(value: Int)創建一個Semaphore。這個value可用來決定可以同時執行的執行程序數量,通常設為1來保證單一執行。當設為1時,表示只有一個執行程序可以繼續執行,這通常用於保證某段代碼的互斥執行(即同一時間只有一個執行緒能夠進入這段代碼)。
當value設為大於1時,意味著允許多個執行程序同時執行,Semaphore會根據這個value來判斷有多少個執行程序可以同時進入臨界區域。例如,設為3時,最多允許三個執行緒同時執行,而超過這個數量的執行緒會被阻塞直到其他執行緒調用signal()釋放資源。
而設為0則意味著初始狀態下所有的執行程序都必須等待,直到有其他程序發出signal()信號。
let semaphore = DispatchSemaphore(value: 0)
使用wait()停止執行程序
wait()會停止執行程序,直到有人使用signal()通知它繼續。在等待的時候,執行程序會被阻塞,不會繼續下作,這就讓你能安全的在記錄後段的計算。
通常會在設置semaphore與wait之間,放入會產生異步執行的程式碼。
semaphore.wait()
使用signal()取消阻塞
signal()使執行程序繼續。你可以在完成了準備工作後,使用signal()通知Semaphore,使待機的執行程序繼續下作。
通常會在異步執行的程式碼完成時呼叫。
semaphore.signal()
以下是一個簡單的實例,如果你有一個組合要在一個主執行程序中同步執行,但這些作業的執行需要等待下來,你就可以使用DispatchSemaphore來做到。
以下的範例,我們使用一個Semaphore來管理一個非常等待的網路請求。
let semaphore = DispatchSemaphore(value: 0)
func fetchDataFromServer(completion: @escaping () -> Void) {
DispatchQueue.global().async {
print("開始請求網路資料...")
sleep(2) // 演示網路請求的等待時間
print("網路資料已請求完畢")
semaphore.signal() // 請求完成,發信號通知
}
}
fetchDataFromServer() // 起始網路請求
semaphore.wait() // 等待網路請求完成
print("完成之後繼續執行")
在這個範例中,我們使用Semaphore來停止主執行程序,以便等待網路請求完成後繼續執行。這一方法很有用,當你需要一些項目準備好以後,才可以繼續進行下一步。
使用DispatchSemaphore時,下面這些是需要特別注意的地方:
signal(),那麼停止的執行程序就會較難繼續。