GCD的知識整理

參考:https://juejin.im/post/5a90de68f265da4e9b592b40

基礎API

// 系統(tǒng)標準提供的兩個隊列
// 全局隊列,也是一個并行隊列  
dispatch_get_global_queue
// 主隊列普办,在主線程中運行液兽,因為主線程只有一個,所以這是一個串行隊列  
dispatch_get_main_queue
// 除此之外,還可以自己生成隊列
// 串行隊列(串行隊列每次只有一個任務被執(zhí)行,任務一個接一個按順序執(zhí)行)
dispatch_queue_create("隊列名", DISPATCH_QUEUE_SERIAL)
// 并行隊列(雖然并發(fā)隊列可以開啟多個線程蠢莺,并且同時執(zhí)行多個任務。但是因為本身不能創(chuàng)建新線程)
dispatch_queue_create("隊列名", DISPATCH_QUEUE_CONCURRENT)
// 接下來是同步與異步線程的創(chuàng)建:
dispatch_sync(..., ^(block)) // 同步線程
dispatch_async(..., ^(block)) // 異步線程
//串行隊列+同步線程不會開啟新線程

1.串行隊列:任務按順序執(zhí)行零如,一個執(zhí)行完畢執(zhí)行下一個任務躏将,無論同步任務或是異步任務,因為串行隊列 執(zhí)行同步任務不開辟線程埠况,執(zhí)行異步任務開辟最多開辟一條線程,所以必須順序執(zhí)行棵癣。
2.并行隊列的特點辕翰,執(zhí)行異步任務具備開辟多條線程的能力,執(zhí)行同步任務狈谊,順序執(zhí)行喜命。因為沒有開辟線程沟沙。
3.開不開線程,取決的任務壁榕,同步不開新線程矛紫,異步開新線程。
4.開幾條線程取決于隊列牌里,串行隊列開一條線程颊咬,并行隊列在執(zhí)行多個異步任務時會開辟多條線程。

dispatch_group 隊列組

分別異步執(zhí)行2個耗時任務牡辽,然后當2個耗時任務都執(zhí)行完畢后再回到主線程執(zhí)行任務喳篇。這時候我們可以用到 GCD 的隊列組。

    //第一步創(chuàng)建隊列
    dispatch_queue_t customQuue = dispatch_queue_create("隊列名稱", DISPATCH_QUEUE_CONCURRENT);
     //第二步創(chuàng)建組
    dispatch_group_t customGroup = dispatch_group_create();
    //第三步添加任務
    dispatch_group_async(customGroup, customQuue, ^{
        NSLog(@"吃飯");
    });
    dispatch_group_async(customGroup, customQuue, ^{
        NSLog(@"洗澡");
    });
    //第四步通知
    dispatch_group_notify(customGroup, dispatch_get_main_queue(), ^{
        NSLog(@"任務完成");
    });

   //dispatch_group_wait暫停當前線程(**阻塞當前線程**)态辛,等待指定的 group 中的任務執(zhí)行完成后麸澜,才會往下繼續(xù)執(zhí)行。
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);


   //這里的dispatch_group_enter奏黑、dispatch_group_leave組合炊邦,其實等同于dispatch_group_async。
    dispatch_group_enter(customGroup);
    dispatch_async(customQuue, ^{
        // 追加任務1
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模擬耗時操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印當前線程
        }
        dispatch_group_leave(group);
    });

dispatch_semaphore 信號量

GCD 中的信號量是指 Dispatch Semaphore熟史,是持有計數(shù)的信號馁害。類似于過高速路收費站的欄桿∫怨剩可以通過時蜗细,打開欄桿,不可以通過時怒详,關閉欄桿炉媒。在 Dispatch Semaphore 中,使用計數(shù)來完成這個功能昆烁,計數(shù)為0時等待吊骤,不可通過。計數(shù)為1或大于1時静尼,計數(shù)減1且不等待白粉,可通過。
Dispatch Semaphore 提供了三個函數(shù)鼠渺。

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

注意:信號量的使用前提是:想清楚你需要處理哪個線程等待(阻塞),又要哪個線程繼續(xù)執(zhí)行普舆,然后使用信號量恬口。
Dispatch Semaphore 在實際開發(fā)中主要用于:
保持線程同步校读,將異步執(zhí)行任務轉(zhuǎn)換為同步執(zhí)行任務
保證線程安全,為線程加鎖

上代碼

/**
 * 線程安全:使用 semaphore 加鎖
 * 初始化火車票數(shù)量祖能、賣票窗口(線程安全)歉秫、并開始賣票
 */
- (void)initTicketStatusSave {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當前線程
    NSLog(@"semaphore---begin");
    
    semaphoreLock = dispatch_semaphore_create(1);
    
    self.ticketSurplusCount = 50;
    // queue1 代表北京火車票售賣窗口
    dispatch_queue_t queue1 = dispatch_queue_create("net.bujige.testQueue1", DISPATCH_QUEUE_SERIAL);
    // queue2 代表上海火車票售賣窗口
    dispatch_queue_t queue2 = dispatch_queue_create("net.bujige.testQueue2", DISPATCH_QUEUE_SERIAL);
    
    __weak typeof(self) weakSelf = self;
    dispatch_async(queue1, ^{
        [weakSelf saleTicketSafe];
    });
    dispatch_async(queue2, ^{
        [weakSelf saleTicketSafe];
    });
}

/**
 * 售賣火車票(線程安全)
 */
- (void)saleTicketSafe {
    while (1) {
        // 相當于加鎖
        dispatch_semaphore_wait(semaphoreLock, DISPATCH_TIME_FOREVER);
        if (self.ticketSurplusCount > 0) {  //如果還有票养铸,繼續(xù)售賣
            self.ticketSurplusCount--;
            NSLog(@"%@", [NSString stringWithFormat:@"剩余票數(shù):%d 窗口:%@", self.ticketSurplusCount, [NSThread currentThread]]);
            [NSThread sleepForTimeInterval:0.2];
        } else { //如果已賣完雁芙,關閉售票窗口
            NSLog(@"所有火車票均已售完");
            // 相當于解鎖
            dispatch_semaphore_signal(semaphoreLock);
            break;
        }
        // 相當于解鎖
        dispatch_semaphore_signal(semaphoreLock);
    }
}
輸出結果為:
2018-02-23 22:32:19.814232+0800 YSC-GCD-demo[20862:5290531] currentThread---<NSThread: 0x6000000783c0>{number = 1, name = main}
2018-02-23 22:32:19.814412+0800 YSC-GCD-demo[20862:5290531] semaphore---begin
2018-02-23 22:32:19.814837+0800 YSC-GCD-demo[20862:5290687] 剩余票數(shù):49 窗口:<NSThread: 0x6040002709c0>{number = 3, name = (null)}
2018-02-23 22:32:20.017745+0800 YSC-GCD-demo[20862:5290689] 剩余票數(shù):48 窗口:<NSThread: 0x60000046c640>{number = 4, name = (null)}
2018-02-23 22:32:20.222039+0800 YSC-GCD-demo[20862:5290687] 剩余票數(shù):47 窗口:<NSThread: 0x6040002709c0>{number = 3, name = (null)}
......
2018-02-23 22:32:29.024817+0800 YSC-GCD-demo[20862:5290689] 剩余票數(shù):4 窗口:<NSThread: 0x60000046c640>{number = 4, name = (null)}
2018-02-23 22:32:29.230110+0800 YSC-GCD-demo[20862:5290687] 剩余票數(shù):3 窗口:<NSThread: 0x6040002709c0>{number = 3, name = (null)}
2018-02-23 22:32:29.433615+0800 YSC-GCD-demo[20862:5290689] 剩余票數(shù):2 窗口:<NSThread: 0x60000046c640>{number = 4, name = (null)}
2018-02-23 22:32:29.637572+0800 YSC-GCD-demo[20862:5290687] 剩余票數(shù):1 窗口:<NSThread: 0x6040002709c0>{number = 3, name = (null)}
2018-02-23 22:32:29.840234+0800 YSC-GCD-demo[20862:5290689] 剩余票數(shù):0 窗口:<NSThread: 0x60000046c640>{number = 4, name = (null)}
2018-02-23 22:32:30.044960+0800 YSC-GCD-demo[20862:5290687] 所有火車票均已售完
2018-02-23 22:32:30.045260+0800 YSC-GCD-demo[20862:5290689] 所有火車票均已售完

柵欄函數(shù)dispatch_barrier_async

dispatch_barrier_async函數(shù),在進程管理中起到一個柵欄的作用揭厚,它等待所有位于barrier函數(shù)之前的操作執(zhí)行完畢后執(zhí)行,并且在barrier函數(shù)執(zhí)行之后,barrier函數(shù)之后的操作才會得到執(zhí)行却特,該函數(shù)需要同dispatch_queue_create函數(shù)生成的DISPATCH_QUEUE_CONCURRENT隊列一起使用。
柵欄函數(shù)的這個特點筛圆,使得它非常適合用于做多讀單寫讀寫鎖裂明。比如說對于一個數(shù)據(jù),可以多線程讀取太援,但是只能單線程修改闽晦,就非常適合用柵欄函數(shù)dispatch_barrier和同步函數(shù)dispatch_sync配合并行隊列做數(shù)據(jù)的讀寫安全機制。

柵欄函數(shù)使用注意事項

為什么不能跟全局并行隊列配合使用呢提岔?
原因在于全局隊列屬于系統(tǒng)創(chuàng)建并管理仙蛉,這個隊列不止我們app在用,系統(tǒng)也在用碱蒙。里面很多涉及到系統(tǒng)自身相關的操作荠瘪,一旦我們外部app阻塞這個隊列,有可能會影響系統(tǒng)相關的操作赛惩。因此柵欄函數(shù)對全局(globa)并行隊列的操作是無效的 (dispatch_get_global_queue)

在
dispatch_queue_t  線程名字 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
中
dispatch_async  = dispatch_barrier_async

線程加鎖

加鎖方式一 dispatch_semaphore 自旋鎖
加鎖方式二 @synchronized 互斥鎖 @synchronized(self) { ---}
加鎖方式三 NSLock --- [_lock lock]; [_lock unlock];

swfit待更新

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哀墓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子喷兼,更是在濱河造成了極大的恐慌篮绰,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件季惯,死亡現(xiàn)場離奇詭異吠各,居然都是意外死亡,警方通過查閱死者的電腦和手機勉抓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門贾漏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人藕筋,你說我怎么就攤上這事纵散。” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵困食,是天一觀的道長。 經(jīng)常有香客問我翎承,道長硕盹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任叨咖,我火速辦了婚禮瘩例,結果婚禮上,老公的妹妹穿的比我還像新娘甸各。我一直安慰自己垛贤,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布趣倾。 她就那樣靜靜地躺著聘惦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪儒恋。 梳的紋絲不亂的頭發(fā)上善绎,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音诫尽,去河邊找鬼禀酱。 笑死,一個胖子當著我的面吹牛牧嫉,可吹牛的內(nèi)容都是我干的剂跟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酣藻,長吁一口氣:“原來是場噩夢啊……” “哼曹洽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起臊恋,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤衣洁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抖仅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坊夫,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年撤卢,在試婚紗的時候發(fā)現(xiàn)自己被綠了环凿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡放吩,死狀恐怖智听,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤到推,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布考赛,位于F島的核電站,受9級特大地震影響莉测,放射性物質(zhì)發(fā)生泄漏颜骤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一捣卤、第九天 我趴在偏房一處隱蔽的房頂上張望忍抽。 院中可真熱鬧,春花似錦董朝、人聲如沸鸠项。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祟绊。三九已至,卻和暖如春哥捕,著一層夾襖步出監(jiān)牢的瞬間久免,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工扭弧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留阎姥,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓鸽捻,卻偏偏與公主長得像呼巴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子御蒲,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

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

  • iOS中多線程 首先看一道面試題 iOS中多線程有哪些實現(xiàn)方案衣赶? iOS中,多線程一般有三種方案GCD厚满、NSOpe...
    木子奕閱讀 655評論 0 1
  • 這篇會整理GCD常用的API 目錄1府瞄、dispatch_after2、dispatch_apply3碘箍、dispat...
    37b32340bcbc閱讀 501評論 0 0
  • 1.GCD隊列有哪幾種類型?有哪幾種隊列遵馆? GCD隊列分為串行隊列、并行隊列兩種類型丰榴;隊列有主串行隊列货邓、全局并行隊...
    oc123閱讀 1,765評論 0 7
  • GCD API函數(shù)整理 GCD(Grand Central Dispatch)是異步執(zhí)行任務的技術之一,一般將應用...
    凌巔閱讀 334評論 0 0
  • GCD多線程整理學習 GCD簡介 iOS中多核編程的解決方法四濒。 主要用于優(yōu)化應用程序以及支持多核處理器以及其他對稱...
    jay_丶閱讀 171評論 0 0