iOS線程間通信 - GCD篇

以下三種方法通過(guò)線程的依賴關(guān)系實(shí)現(xiàn)線程同步:

1.組隊(duì)列(dispatch_group_t)

2.阻塞任務(wù)(dispatch_barrier_(a)sync)

3.信號(hào)量機(jī)制(dispatch_semaphore)

1.組隊(duì)列(dispatch_group_t):

舉一個(gè)例子:用戶下載一個(gè)圖片震庭,圖片很大,需要分成很多份進(jìn)行下載压语,使用GCD應(yīng)該如何實(shí)現(xiàn)榄鉴?使用什么隊(duì)列?

使用Dispatch Group追加block到Global Group Queue渡贾,這些block如果全部執(zhí)行完畢逗宜,就會(huì)執(zhí)行通過(guò)dispatch_group_notify添加到主隊(duì)列中的block,進(jìn)行圖片的合并處理。

?dispatch_group_t group = dispatch_group_create();
??? dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
??????? //請(qǐng)求1
??????? [self request_A];
??? });
??? dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
??????? //請(qǐng)求2
??????? [self request_B];
??? });
??? dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
??????? //請(qǐng)求3
???????? [self request_C];
??? });
??? dispatch_group_notify(group, dispatch_get_main_queue(), ^{
??????? //界面刷新
??????? NSLog(@"任務(wù)均完成纺讲,刷新界面");
??? });

2.阻塞任務(wù)(dispatch_barrier):

通過(guò)dispatch_barrier_async添加的操作會(huì)暫時(shí)阻塞當(dāng)前隊(duì)列擂仍,即等待前面的并發(fā)操作都完成后執(zhí)行該阻塞操作,待其完成后后面的并發(fā)操作才可繼續(xù)熬甚》暧妫可以將其比喻為一根霸道的獨(dú)木橋,是并發(fā)隊(duì)列中的一個(gè)并發(fā)障礙點(diǎn)乡括,或者說(shuō)中間瓶頸肃廓,臨時(shí)阻塞并獨(dú)占。注意dispatch_barrier_async只有在并發(fā)隊(duì)列中才能起作用诲泌,在串行隊(duì)列中隊(duì)列本身就是獨(dú)木橋盲赊,將失去其意義。

可見使用dispatch_barrier_async可以實(shí)現(xiàn)類似dispatch_group_t組調(diào)度的效果,同時(shí)主要的作用是避免數(shù)據(jù)競(jìng)爭(zhēng)敷扫,高效訪問數(shù)據(jù)哀蘑。

/* 創(chuàng)建并發(fā)隊(duì)列 */

dispatch_queue_t concurrentQueue=dispatch_queue_create("test.concurrent.queue",DISPATCH_QUEUE_CONCURRENT);

/* 添加兩個(gè)并發(fā)操作A和B,即A和B會(huì)并發(fā)執(zhí)行 */

dispatch_async(concurrentQueue,^({NSLog(@"OperationA");});

dispatch_async(concurrentQueue,^(){NSLog(@"OperationB");});

/* 添加barrier障礙操作葵第,會(huì)等待前面的并發(fā)操作結(jié)束绘迁,并暫時(shí)阻塞后面的并發(fā)操作直到完成*/

dispatch_barrier_async(concurrentQueue,^(){NSLog(@"OperationBarrier!");});

/* 繼續(xù)添加并發(fā)操作C和D,要等待barrier障礙操作結(jié)束才能開始*/

dispatch_async(concurrentQueue,^({NSLog(@"OperationC");});

dispatch_async(concurrentQueue,^(){NSLog(@"OperationD");});

執(zhí)行結(jié)果如下:

2017-04-04 12:25:02.344 SingleView[12818:3694480] OperationB

2017-04-04 12:25:02.344 SingleView[12818:3694482] OperationA

2017-04-04 12:25:02.345 SingleView[12818:3694482] OperationBarrier!

2017-04-04 12:25:02.345 SingleView[12818:3694482] OperationD

2017-04-04 12:25:02.345 SingleView[12818:3694480] OperationC

3.信號(hào)量機(jī)制(dispatch_semaphore):

信號(hào)量機(jī)制主要是通過(guò)設(shè)置有限的資源數(shù)量來(lái)控制線程的最大并發(fā)數(shù)量以及阻塞線程實(shí)現(xiàn)線程同步等羹幸。

GCD中使用信號(hào)量需要用到三個(gè)函數(shù):

dispatch_semaphore_create用來(lái)創(chuàng)建一個(gè)semaphore信號(hào)量并設(shè)置初始信號(hào)量的值脊髓;

dispatch_semaphore_signal發(fā)送一個(gè)信號(hào)讓信號(hào)量增加1(對(duì)應(yīng)PV操作的V操作);

dispatch_semaphore_wait等待信號(hào)使信號(hào)量減1(對(duì)應(yīng)PV操作的P操作)栅受;

那么如何通過(guò)信號(hào)量來(lái)實(shí)現(xiàn)線程同步呢将硝?下面介紹使用GCD信號(hào)量來(lái)實(shí)現(xiàn)任務(wù)間的依賴和最大并發(fā)任務(wù)數(shù)量的控制。

使用信號(hào)量實(shí)現(xiàn)任務(wù)2依賴于任務(wù)1屏镊,即任務(wù)2要等待任務(wù)1結(jié)束才開始執(zhí)行:

方法很簡(jiǎn)單依疼,創(chuàng)建信號(hào)量并初始化為0,讓任務(wù)2執(zhí)行前等待信號(hào)而芥,實(shí)現(xiàn)對(duì)任務(wù)2的阻塞律罢。然后在任務(wù)1完成后再發(fā)送信號(hào),從而任務(wù)2獲得信號(hào)開始執(zhí)行棍丐。需要注意的是這里任務(wù)1和2都是異步提交的误辑,如果沒有信號(hào)量的阻塞,任務(wù)2是不會(huì)等待任務(wù)1的,實(shí)際上這里使用信號(hào)量實(shí)現(xiàn)了兩個(gè)任務(wù)的同步歌逢。

通過(guò)打印的時(shí)間可以看到任務(wù)2是在任務(wù)1結(jié)束后緊接著執(zhí)行的:

執(zhí)行結(jié)果

通過(guò)信號(hào)量控制最大并發(fā)數(shù)量:

通過(guò)信號(hào)量控制最大并發(fā)數(shù)量的方法為:創(chuàng)建信號(hào)量并初始化信號(hào)量為想要控制的最大并發(fā)數(shù)量巾钉,例如想要保證最大并發(fā)數(shù)為5,則信號(hào)量初始化為5秘案。然后在每個(gè)新任務(wù)執(zhí)行前進(jìn)行P操作砰苍,等待信號(hào)使信號(hào)量減1潦匈;每個(gè)任務(wù)結(jié)束后進(jìn)行V操作,發(fā)送信號(hào)使信號(hào)量加1赚导。這樣即可保證信號(hào)量始終在5以內(nèi)茬缩,當(dāng)前最多也只有5個(gè)以內(nèi)的任務(wù)在并發(fā)執(zhí)行。

打印結(jié)果為每次開啟五個(gè)并發(fā)任務(wù):

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吼旧,一起剝皮案震驚了整個(gè)濱河市凰锡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌黍少,老刑警劉巖寡夹,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異厂置,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)魂角,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門昵济,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人野揪,你說(shuō)我怎么就攤上這事访忿。” “怎么了斯稳?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵海铆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我挣惰,道長(zhǎng)卧斟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任憎茂,我火速辦了婚禮珍语,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘竖幔。我一直安慰自己板乙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布拳氢。 她就那樣靜靜地躺著募逞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪馋评。 梳的紋絲不亂的頭發(fā)上放接,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音栗恩,去河邊找鬼透乾。 笑死洪燥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的乳乌。 我是一名探鬼主播捧韵,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼汉操!你這毒婦竟也來(lái)了再来?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤磷瘤,失蹤者是張志新(化名)和其女友劉穎芒篷,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體采缚,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡针炉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扳抽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篡帕。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贸呢,靈堂內(nèi)的尸體忽然破棺而出镰烧,到底是詐尸還是另有隱情,我是刑警寧澤楞陷,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布怔鳖,位于F島的核電站,受9級(jí)特大地震影響固蛾,放射性物質(zhì)發(fā)生泄漏结执。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一魏铅、第九天 我趴在偏房一處隱蔽的房頂上張望昌犹。 院中可真熱鬧,春花似錦览芳、人聲如沸斜姥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铸敏。三九已至,卻和暖如春悟泵,著一層夾襖步出監(jiān)牢的瞬間杈笔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工糕非, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蒙具,地道東北人球榆。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像禁筏,于是被迫代替她去往敵國(guó)和親持钉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345