Swift GCD的進(jìn)階用法

1、信號量(Semaphore)

定義:信號量就是一個資源計數(shù)器,就是一種可用來控制訪問資源數(shù)量的標(biāo)識。

通過添加信號量的處理,則可告訴系統(tǒng)按照我們指定的信號量數(shù)量來執(zhí)行多個線程。類似鎖機(jī)制。
更通俗的來理解信號量其實就像是一間可容納n個人的教室(初始信號量為n),上課鈴響了(程序進(jìn)程運(yùn)行),n個學(xué)生(即對應(yīng)n條線程)都跑進(jìn)了該教室坐滿了位置,好好聽課~此時座位坐滿,沒座位了(即信號量為0),其他小伙伴想進(jìn)這個教室聽課也進(jìn)不來了。中間有兩個學(xué)生突然覺得尿意襲來,就相約跑出去上廁所了。此時教室里就空出來兩個位置(信號量+2),其他小伙伴就可以趁這個機(jī)會進(jìn)來聽課~這時候教室又被坐滿了(信號量-2),剛剛?cè)瞿虻膬蓚€同學(xué)回來發(fā)現(xiàn)沒位置了,只能被擋在門外(阻塞)不得進(jìn)教室聽課學(xué)習(xí),大體流程就是這樣啦~

舉個??

信號量圖1

信號量圖2

輸出結(jié)果可知:可以觀察到當(dāng)注釋掉semaphore.wait()這一行,i的輸出結(jié)果不同。原因:由于我們是將block異步添加到一個并行隊列里面(子線程),所以程序執(zhí)行的時候會先執(zhí)行主線程的代碼,直接執(zhí)行到semaphore.wait()這一行,因為此時的semaphore的信號量為0,所以當(dāng)前線程會一直阻塞,直到block在子線程執(zhí)行到semaphore.signal()這一行,使得信號量+1,進(jìn)而程序可以繼續(xù)往下走。

再舉個??,為線程加鎖

同時可以控制最大并發(fā)數(shù)量,value的值決定最多幾個并發(fā)。

func semaphore2() {
    let semaphore = DispatchSemaphore(value: 1)
    for i in 0..<100 {
        DispatchQueue.global().async {
            semaphore.wait()
            print("i =", i)
            semaphore.signal()
        }
    }
}

當(dāng)子線程1執(zhí)行到semaphore.wait()這一行的時候,semaphore的信號量為1,所以此時-1變?yōu)?,并且子線程1繼續(xù)往下執(zhí)行;如果當(dāng)在子線程1的print這一行代碼還沒執(zhí)行完的時候,又有子線程2訪問進(jìn)來了,同樣執(zhí)行到semaphore.wait()時,由于此時信號量為0(注意:.wait()方法默認(rèn)時間是 OC 的DISPATCH_TIME_FOREVER),所以會一直阻塞子線程2(此時子線程2就處于等待狀態(tài)),直到子線程1執(zhí)行完print并執(zhí)行完semaphore.signal()使信號量+1等于1后,子線程2才可以不被阻塞繼續(xù)往下執(zhí)行。這樣就可以保證同時只有一個子線程執(zhí)行print這一行代碼。

加一把小鎖??

func synchronized(_ lock: AnyObject, _ closure: () -> Void) {
    objc_sync_enter(lock)
    closure()
    objc_sync_exit(lock)
}

// 實現(xiàn)一個線程安全的setter
class Obj {
    var _str = "123"
    var str: String {
        get { return _str }
        set {
            self.synchronized(self) {
                _str = newValue
            }
        }
    }
}

實際應(yīng)用小??

在開發(fā)中,我們有時候會需要等待某個網(wǎng)絡(luò)回調(diào)完成之后再繼續(xù)進(jìn)行下一操作,就可以這樣寫:


并發(fā)隊列信號量

2、柵欄函數(shù)(barrier)

使用barrier函數(shù)可以做到異步執(zhí)行多個任務(wù)完成后,再執(zhí)行之后的任務(wù),它會阻塞當(dāng)前子線程。

柵欄函數(shù)(barrier)

3、GCD組的用法(Group)

使用group + notify的話,也會等待隊列的任務(wù)先執(zhí)行完畢,和柵欄函數(shù)的區(qū)別在于它不會阻塞當(dāng)前子線程。

group + notify

wait + group組合

wait + group

使用wait + group的話,會等待隊列的任務(wù)先執(zhí)行,且阻塞當(dāng)前子線程,如若出現(xiàn)超時,則會執(zhí)行往下繼續(xù)執(zhí)行,上面的任務(wù)依舊繼續(xù)執(zhí)行。此處的timeout可設(shè)置為distantFuture即無限等待(類似barrier函數(shù))。

進(jìn)階用法暫且就這么多啦,一定要多寫多嘗試多用,方可得心應(yīng)手。


部分資料來源于網(wǎng)絡(luò),若侵權(quán),請聯(lián)系刪除~
聯(lián)系方式:kim77895pl@gmail.com
Kim 寫于2020.8.18,希望文章能對你有所幫助。

?著作權(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ù)。

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