GCD的使用

iOS實(shí)際上算是unix的一個(gè)分支白粉,所以iOS上的多線程可以使用pthread。不過(guò)Apple另外提供了GCD來(lái)簡(jiǎn)化多線程編程鼠渺,實(shí)際上GCD是基于pthread的蜗元。大部分情況下使用iOS多線程都是和I/O相關(guān)的,需要記住UI相關(guān)的操作必須是單線程(main thread)的系冗。

在GCD中我們并不是直接創(chuàng)建線程,而是使用queue(隊(duì)列)薪鹦。GCD中的queue分為兩類:Serial和Concurrent掌敬,前者是需要等待前一個(gè)任務(wù)結(jié)束的惯豆,后者并不需要(任務(wù)執(zhí)行順序只有上帝才知道)。我們可以使用 dispatch_queue_create函數(shù)創(chuàng)建一個(gè)queue奔害。

//默認(rèn)是Serial
dispatch_queue_create("ax_serial_queue", NULL/*DISPATCH_QUEUE_SERIAL*/);
dispatch_queue_create("ax_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

也可以直接獲取iOS為我們提供的queue楷兽。iOS為我們提供了兩個(gè)queue: ** Main Dispatch Queue ** (主線程)、Global Dispatch Queue华临,前者是Serial后者是Concurrent芯杀。其中Global Dispatch Queue有四種運(yùn)行級(jí)別:high、default雅潭、low揭厚、background。

dispatch_get_main_queue()
//下面的第二個(gè)參數(shù)一般為0扶供,目前沒(méi)有使用這個(gè)參數(shù)筛圆。
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

創(chuàng)建/獲取了queue之后就可以向queue中添加任務(wù),常用的是dispatch_async椿浓,這個(gè)是異步的太援,即不等待任務(wù)完成,dispatch_sync是同步的扳碍,即等待任務(wù)完成提岔。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
{
    printf("block 1\n"):
});

直接執(zhí)行上面的代碼很可能會(huì)沒(méi)有輸出結(jié)果,:-D主線程已經(jīng)結(jié)束了(可以使用sleep試試)笋敞。為了更方便地管理碱蒙,我們可以使用group。group使用dispatch_group_create()直接創(chuàng)建液样,然后將上面的dispatch_async改為dispatch_group_async即可振亮。

 dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 dispatch_group_t group=dispatch_group_create();

 dispatch_group_async(group, queue, ^{printf("block1\n");});
 dispatch_group_async(group, queue, ^{printf("block2\n");});
 dispatch_group_async(group, queue, ^{printf("block3\n");});
 dispatch_group_async(group, queue, ^{printf("block4\n");});

 dispatch_group_notify(group, dispatch_get_main_queue(), ^{printf("block done\n");});

 /*也可以試試下面的代碼
 dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
 printf("block done\n");*/

上面的代碼可以等待任務(wù)全部完成并輸出結(jié)果,不過(guò)可能會(huì)有點(diǎn)小問(wèn)題,如果是在主線程中執(zhí)行上面的代碼鞭莽,block done結(jié)果并沒(méi)有看到坊秸。這是因?yàn)橹骶€程的queue是Serial的,新任務(wù)要等主線程結(jié)束才會(huì)執(zhí)行澎怒。

dispatch_group_notify(group, queue, ^{printf("block done\n");});

修改之后就沒(méi)有問(wèn)題了褒搔。dispatch_group_notifydispatch_group_wait函數(shù)的使用就不再過(guò)多的說(shuō)明了喷面。

通常情況下星瘾,使用多線程要注意讀寫鎖。讀可以多個(gè)線程一起讀惧辈,寫只能一個(gè)線程寫琳状。在多個(gè)dispatch_async中插入dispatch_barrier_async就可以實(shí)現(xiàn)pthread的讀寫鎖的效果。

dispatch_async(concurrent_queue, ^{printf("1\n");});
dispatch_async(concurrent_queue, ^{printf("2\n");});
    
dispatch_barrier_async(concurrent_queue, ^{printf("3\n");});

dispatch_async(concurrent_queue, ^{printf("4\n");});
dispatch_async(concurrent_queue, ^{printf("5\n");});

執(zhí)行順序是1/2 => 3 =>4/5盒齿,1和2的順序不定念逞,4和5的順序不定困食,3必然在1、2之后以及4翎承、5之前硕盹。

如何寫一個(gè)線程安全的單列了?這是面試中常問(wèn)的一個(gè)問(wèn)題叨咖。GCD中使用dispatch_once可以簡(jiǎn)單高效的完成這一類任務(wù)瘩例。

static dispatch_once_t classA_once;
dispatch_once(&classA_once,^
{
    //initialization
});

GCD中還有諸如Semaphore、I/O的內(nèi)容甸各,不過(guò)實(shí)際中這些內(nèi)容使用的比較少垛贤,就在此跳過(guò)了。使用GCD進(jìn)行多線程編程需要我們注意的就是死鎖痴晦,比如在主線程中運(yùn)行dispatch_sync(dispatch_get_main_queue(),^{......});會(huì)直接導(dǎo)致程序crash這樣的嚴(yán)重后果南吮。我們需要慎重地使用dispatch_sync函數(shù),上面group案例中的在dispatch_get_main_queue中使用dispatch_async也沒(méi)有想我們想象的一樣執(zhí)行誊酌。

如有錯(cuò)誤部凑,歡迎指出!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碧浊,一起剝皮案震驚了整個(gè)濱河市涂邀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箱锐,老刑警劉巖比勉,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異驹止,居然都是意外死亡浩聋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門臊恋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)衣洁,“玉大人,你說(shuō)我怎么就攤上這事抖仅》环颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵撤卢,是天一觀的道長(zhǎng)环凿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)放吩,這世上最難降的妖魔是什么智听? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上瞭稼,老公的妹妹穿的比我還像新娘忽洛。我一直安慰自己,他們只是感情好环肘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著集灌,像睡著了一般悔雹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上欣喧,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天腌零,我揣著相機(jī)與錄音,去河邊找鬼唆阿。 笑死益涧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的驯鳖。 我是一名探鬼主播闲询,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼浅辙!你這毒婦竟也來(lái)了扭弧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤记舆,失蹤者是張志新(化名)和其女友劉穎鸽捻,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泽腮,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡御蒲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诊赊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厚满。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖豪筝,靈堂內(nèi)的尸體忽然破棺而出痰滋,到底是詐尸還是另有隱情,我是刑警寧澤续崖,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布敲街,位于F島的核電站,受9級(jí)特大地震影響严望,放射性物質(zhì)發(fā)生泄漏多艇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一像吻、第九天 我趴在偏房一處隱蔽的房頂上張望峻黍。 院中可真熱鬧复隆,春花似錦、人聲如沸姆涩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骨饿。三九已至亏栈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宏赘,已是汗流浹背绒北。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留察署,地道東北人闷游。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像贴汪,于是被迫代替她去往敵國(guó)和親脐往。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容