【iOS】GCD 之 Semaphore 信號量

參考資料:

  1. Medium : The Beauty of Semaphores in Swift
  2. Medium : A Quick Look At Semaphore
  3. 不羈閣:『GCD』詳盡總結(jié)
Semaphore信號量主要用途有兩個:
  1. 用于多線程對共享資源的訪問控制,保證線程安全,為線程加鎖。
  2. 保持線程同步,將異步任務(wù)轉(zhuǎn)換為同步任務(wù)。

Tip : 共享資源可以是一個變量,一個從url下載圖片的任務(wù),讀取數(shù)據(jù)庫的任務(wù)等等。

一些理論知識(A Bit of Theory)

信號量是由一個線程隊列和一個計數(shù)器(Int類型)組成的。

線程隊列(Threads Queue) : 采用FIFO先進(jìn)先出機(jī)制用來追蹤等待線程(等待訪問共享資源的線程)。

計數(shù)器(Counter Value) : 用來決定一個線程是否可以訪問共享資源。(waitsignal方法都將改變計數(shù)器的值)

那么,我們什么時候調(diào)用waitsignal方法呢?

  • 訪問共享資源之前調(diào)用wait方法。wait方法可以理解為當(dāng)前線程在請求對共享資源的訪問,如果資源可用(未被其他線程占用)則允許訪問,否則等待(阻塞線程)。
  • 訪問共享資源結(jié)束之后調(diào)用signal方法。結(jié)束訪問時,要通知信號量,我用完了資源,讓別人(等待著的線程)來訪問吧。

調(diào)用wait方法時,行為規(guī)則如下:

  • 計數(shù)器-1;
  • 如果-1之后,當(dāng)前計數(shù)器小于0,則線程被阻塞;
  • 如果-1之后,當(dāng)前計數(shù)器大于等于0,則線程被放行,無需等待;

調(diào)用signal方法時,行為規(guī)則如下:

  • 計數(shù)器+1;
  • 如果+1之前,計數(shù)器小于0,此方法將從線程隊列中按照FIFO規(guī)則提取第一個等待中的線程并喚醒。
  • 如果+1之前,計數(shù)器大于等于0,說明線程隊列是空的,沒有正在等待的線程。

上面所述流程可用圖示表示如下:


wait和signal執(zhí)行規(guī)則圖示

具體的例子可以查看上面文章中的例子(文章需要翻墻?。。?/p>

這里重點總結(jié)幾點實際使用過程中的小Tip:

  • wait方法有一個等待超時時間參數(shù)(尤其注意參數(shù)是.distantFuture(無限期等待下去)情況下不要在主線程中調(diào)用wait方法,可能將阻塞主線程。)
  • 調(diào)用wait計數(shù)器即刻-1,等待結(jié)果為success時,計數(shù)器保持不變,由signal負(fù)責(zé)回歸計數(shù)器,但是如果等待結(jié)果是timedOut,計數(shù)器將自動+1回歸,因此,應(yīng)只在結(jié)果是success時才執(zhí)行signal操作。
  • 構(gòu)造信號量時傳入的初始計數(shù)器數(shù)值,首先不允許為負(fù)值,其次為0時一般用于將異步任務(wù)轉(zhuǎn)成同步任務(wù),數(shù)值大于0時代表最多允許多少個線程同時訪問共享資源或者同時執(zhí)行多少個任務(wù)。

代碼示例:

  1. 異步任務(wù)轉(zhuǎn)同步任務(wù)

     var value = 10
     let semaphore = DispatchSemaphore(value: 0)
     var waitResult: DispatchTimeoutResult = .success
     DispatchQueue.global().async {
         value = 100
         Thread.sleep(forTimeInterval: 3.0)
         if waitResult == .success {
             semaphore.signal()
         }
     }
     // 試著將這里的超時時間參數(shù)改改查看效果
     waitResult = semaphore.wait(timeout: DispatchTime.distantFuture)
     switch waitResult {
     case .success:
         print("success")
     case .timedOut:
         print("timedOut")
     }
    
  2. 查看不羈閣:『GCD』詳盡總結(jié)的文章末尾,這里講到了信號量及其應(yīng)用示例。

了解一些概念:
優(yōu)先級反轉(zhuǎn)問題及解決方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 在看AFNetworking3.0源碼時,注意到在 AFURLSessionManager.m 里面的 ta...
    路飛_Luck閱讀 2,166評論 2 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評論 19 139
  • 2016年國慶假期終于把此書過完,整理筆記和體會于此。 關(guān)于書名 書名源于俄羅斯的演員斯坦尼斯拉夫斯基創(chuàng)作的《演員...
    李劍飛的簡書閱讀 7,439評論 2 65
  • 上周寫了一篇文章,寫完以后就滿心希望的投給了一個公眾號,結(jié)果就顯而易見了。 理所當(dāng)然的石沉大海,過了幾天我重新找出...
    我是阮七閱讀 168評論 0 0
  • 今天是周五,又到了我們家老大學(xué)舞蹈的日子了,今天晚上,難得在家,所以我就去學(xué)校接她,結(jié)果她在接受老師的懲罰,...
    萬瑞瑩閱讀 190評論 0 0

友情鏈接更多精彩內(nèi)容