GCD復(fù)習(xí)

GCD的優(yōu)勢

  • GCD 可用于多核的并行運(yùn)算
  • GCD 會自動(dòng)利用更多的 CPU 內(nèi)核(比如雙核、四核)
  • GCD會自動(dòng)管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程)
  • 程序員只需要告訴 GCD 想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼

** GCD 任務(wù)和隊(duì)列**

任務(wù):在線程中執(zhí)行操作代碼,在 GCD 中是放在 block 中的。
執(zhí)行任務(wù)有兩種方式:
同步執(zhí)行(sync)和異步執(zhí)行(async)。

同步執(zhí)行(sync)
同步添加任務(wù)到指定的隊(duì)列中,在添加的任務(wù)執(zhí)行結(jié)束之前,會一直等待,直到隊(duì)列里面的任務(wù)完成之后再繼續(xù)執(zhí)行。
只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力。

異步執(zhí)行(async)
異步添加任務(wù)到指定的隊(duì)列中,它不會做任何等待,可以繼續(xù)執(zhí)行任務(wù)。
可以在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力。

隊(duì)列(Dispatch Queue)
隊(duì)列指執(zhí)行任務(wù)的等待隊(duì)列,即用來存放任務(wù)的隊(duì)列。隊(duì)列是一種特殊的線性表,采用 FIFO(先進(jìn)先出)

串行隊(duì)列(Serial Dispatch Queue)
每次只有一個(gè)任務(wù)被執(zhí)行。讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行。(只開啟一個(gè)線程,一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù))

并發(fā)隊(duì)列(Concurrent Dispatch Queue)
可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行。(可以開啟多個(gè)線程,并且同時(shí)執(zhí)行任務(wù))

并發(fā)隊(duì)列的并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效

GCD 的使用步驟

  • 創(chuàng)建一個(gè)隊(duì)列(串行隊(duì)列或并發(fā)隊(duì)列)
  • 將任務(wù)追加到任務(wù)的等待隊(duì)列中,系統(tǒng)會根據(jù)任務(wù)類型執(zhí)行任務(wù)(同步執(zhí)行或異步執(zhí)行)

特別注意

  • 在主線程中調(diào)用同步執(zhí)行 + 主隊(duì)列 = 死鎖
  • 在子線程中調(diào)用同步執(zhí)行 + 主隊(duì)列 = 串行執(zhí)行

GCD 線程間的通信

在其他線程中先執(zhí)行任務(wù),執(zhí)行完了之后回到主線程執(zhí)行主線程的相應(yīng)操作

GCD 的其他方法

  • GCD 柵欄方法:dispatch_barrier_async
    函數(shù)會等待前邊追加到并發(fā)隊(duì)列中的任務(wù)全部執(zhí)行完畢之后,再將指定的任務(wù)追加到該異步隊(duì)列中

  • GCD 延時(shí)執(zhí)行方法:dispatch_after
    在指定時(shí)間之后將任務(wù)追加到主隊(duì)列中。但時(shí)間并不精確

  • GCD 一次性代碼(只執(zhí)行一次):dispatch_once
    在創(chuàng)建單例、或者有整個(gè)程序運(yùn)行過程中只執(zhí)行一次的代碼時(shí),就用到了 GCD 的這個(gè)函數(shù),能保證某段代碼在程序運(yùn)行過程中只被執(zhí)行1次,并且即使在多線程的環(huán)境下,也可以保證線程安全。

  • GCD 快速迭代方法:dispatch_apply
    按照指定的次數(shù)將指定的任務(wù)追加到指定的隊(duì)列中,并等待全部隊(duì)列執(zhí)行結(jié)束。

  • 串行隊(duì)列中使用 dispatch_apply,就和for循環(huán)一樣,按順序同步執(zhí)行。

  • 異步并行隊(duì)列使用,在多個(gè)線程中同時(shí)執(zhí)行,順序不可控。

  • GCD 隊(duì)列組:dispatch_group
    分別異步執(zhí)行2個(gè)耗時(shí)任務(wù),然后當(dāng)2個(gè)耗時(shí)任務(wù)都執(zhí)行完畢后再回到主線程執(zhí)行任務(wù)。這時(shí)候我們可以用到 GCD 的隊(duì)列組。

  • 調(diào)用隊(duì)列組的 dispatch_group_async 先把任務(wù)放到隊(duì)列中,然后將隊(duì)列放入隊(duì)列組中?;蛘呤褂藐?duì)列組的 dispatch_group_enter、dispatch_group_leave組合 來實(shí)現(xiàn)dispatch_group_async。

  • 調(diào)用隊(duì)列組的 dispatch_group_notify 回到指定線程執(zhí)行任務(wù)。或者使用 dispatch_group_wait 回到當(dāng)前線程繼續(xù)向下執(zhí)行(會阻塞當(dāng)前線程)。

dispatch_group_notify
監(jiān)聽 group 中任務(wù)的完成狀態(tài),當(dāng)所有的任務(wù)都執(zhí)行完成后,才執(zhí)行dispatch_group_notify block中追加的任務(wù)。

dispatch_group_wait
暫停當(dāng)前線程(阻塞當(dāng)前線程),等待指定的 group 中的任務(wù)執(zhí)行完成后,才會往下繼續(xù)執(zhí)行。
使用dispatch_group_wait 會阻塞當(dāng)前線程。

dispatch_group_enter、dispatch_group_leave
dispatch_group_enter 標(biāo)志著一個(gè)任務(wù)追加到 group,執(zhí)行一次,相當(dāng)于 group 中未執(zhí)行完畢任務(wù)數(shù)+1

dispatch_group_leave 標(biāo)志著一個(gè)任務(wù)離開了 group,執(zhí)行一次,相當(dāng)于 group 中未執(zhí)行完畢任務(wù)數(shù)-1。

當(dāng) group 中未執(zhí)行完畢任務(wù)數(shù)為0的時(shí)候,才會使dispatch_group_wait解除阻塞,以及執(zhí)行追加到dispatch_group_notify中的任務(wù)。

dispatch_group_enter、dispatch_group_leave組合,其實(shí)等同于dispatch_group_async。

GCD 信號量:dispatch_semaphore
GCD中的信號量是指 Dispatch Semaphore,是持有計(jì)數(shù)的信號。
計(jì)數(shù)為0時(shí)等待,不可通過。
計(jì)數(shù)為1或大于1時(shí),計(jì)數(shù)減1且不等待,可通過。

Dispatch Semaphore 提供了三個(gè)函數(shù)。

  • dispatch_semaphore_create:創(chuàng)建一個(gè)Semaphore并初始化信號的總量
  • dispatch_semaphore_signal:發(fā)送一個(gè)信號,讓信號總量加1
  • dispatch_semaphore_wait:可以使總信號量減1,當(dāng)信號總量為0時(shí)就會一直等待(阻塞所在線程),否則就可以正常執(zhí)行。

注意:信號量的使用前提是:想清楚你需要處理哪個(gè)線程等待(阻塞),又要哪個(gè)線程繼續(xù)執(zhí)行,然后使用信號量。

Dispatch Semaphore 線程同步

  • 保持線程同步,將異步執(zhí)行任務(wù)轉(zhuǎn)換為同步執(zhí)行任務(wù)
  • 保證線程安全,為線程加鎖
    異步執(zhí)行耗時(shí)任務(wù),并使用異步執(zhí)行的結(jié)果進(jìn)行一些額外的操作。== 將異步執(zhí)行任務(wù)轉(zhuǎn)換為同步執(zhí)行任務(wù)。
    AFURLSessionManager.m 里面的 tasksForKeyPath: 方法。通過引入信號量的方式,等待異步執(zhí)行任務(wù)結(jié)果,獲取到 tasks,然后再返回該 tasks。

線程安全(使用 semaphore 加鎖)
semaphore 數(shù)為1線程安全加鎖

dispatch_semaphore_create 創(chuàng)建一個(gè)信號量,傳入數(shù)字為信號總量。到0位鎖
dispatch_semaphore_signal 信號量+1 相當(dāng)于解鎖
dispatch_semaphore_wait 信號量-1 相當(dāng)于加鎖

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

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