GCD相關(guān)基礎(chǔ)知識(shí)

我看世界
原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明:轉(zhuǎn)自:Try_Try_Try

1.獲取Dispatch Queue 的兩種方法

  • 方法一: 通過(guò)GCD api 生成隊(duì)列dispatch_queue_create
  // 串行隊(duì)列
    dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);
    dispatch_async(mySerialDispatchQueue, ^{
    });
    dispatch_release(mySerialDispatchQueue);
    
   // 并行隊(duì)列
    dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(myConcurrentDispatchQueue, ^{
        NSLog(@"block on myConcurrentDispatchQueue");
    });
    dispatch_release(myConcurrentDispatchQueue);
  • 方法二: 獲取系統(tǒng)標(biāo)準(zhǔn)提供的 Dispatch Queue
  // 主隊(duì)列   
    dispatch_queue_t mainDispatchQueue =   dispatch_get_main_queue();
    
  // 全局并發(fā)隊(duì)列(4種優(yōu)先級(jí))
    dispatch_queue_t globalDispatchQueueHeigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

2.延時(shí)操作

  • 3s后,將block追加到主隊(duì)列中進(jìn)行執(zhí)行;
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        NSLog(@"waited at least 3 seconds");
    });

3.隊(duì)列組

  • 在一系列操作完成之后,再執(zhí)行其他內(nèi)容
    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, ^{
        NSLog(@"blk0");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk2");
    });
    
    // 推薦
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"done");
    });

  // 不推薦
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1);
    long result = dispatch_group_wait(group, time);
    if (result == 0) { // group 的全部處理執(zhí)行結(jié)束
    }else {
    }
//    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
    dispatch_release(group);

4.柵欄函數(shù)

  • 用于讀寫(xiě)操作引起的相關(guān)內(nèi)容;
  • 每次的執(zhí)行結(jié)果可能不一樣,但是寫(xiě)操作一定會(huì)將0,1,2,3讀操作和4,5,6,7分隔開(kāi),從而達(dá)到不會(huì)誤讀的效果
    dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
    
    __block NSInteger count = 1;
    
    void (^blk0_for_reading)(void) = ^{NSLog(@"blk0_for_reading-%li%@", count, [NSThread currentThread]);};
    void (^blk1_for_reading)(void) = ^{NSLog(@"blk1_for_reading-%li%@", count, [NSThread currentThread]);};
    void (^blk2_for_reading)(void) = ^{NSLog(@"blk2_for_reading-%li%@", count,[NSThread currentThread]);};
    void (^blk3_for_reading)(void) = ^{NSLog(@"blk3_for_reading-%li%@", count,[NSThread currentThread]);};
    
    void (^blk4_for_writing)(void) = ^{ ++count; NSLog(@"---------blk4_for_writing-%li%@", count,[NSThread currentThread]);};
    
    void (^blk5_for_reading)(void) = ^{NSLog(@"blk5_for_reading-%li%@", count,[NSThread currentThread]);};
    void (^blk6_for_reading)(void) = ^{NSLog(@"blk6_for_reading-%li%@", count,[NSThread currentThread]);};
    void (^blk7_for_reading)(void) = ^{NSLog(@"blk7_for_reading-%li%@", count,[NSThread currentThread]);};
    void (^blk8_for_reading)(void) = ^{NSLog(@"blk8_for_reading-%li%@", count,[NSThread currentThread]);};
    
    dispatch_async(myConcurrentDispatchQueue, blk0_for_reading);
    dispatch_async(myConcurrentDispatchQueue, blk1_for_reading);
    dispatch_async(myConcurrentDispatchQueue, blk2_for_reading);
    dispatch_async(myConcurrentDispatchQueue, blk3_for_reading);
    
    dispatch_barrier_async(myConcurrentDispatchQueue, blk4_for_writing);
    
    dispatch_async(myConcurrentDispatchQueue, blk5_for_reading);
    dispatch_async(myConcurrentDispatchQueue, blk6_for_reading);
    dispatch_async(myConcurrentDispatchQueue, blk7_for_reading);
    dispatch_async(myConcurrentDispatchQueue, blk8_for_reading);

// 結(jié)果
blk1_for_reading-1<NSThread: 0x170272e80>{number = 5, name = (null)}
2017-10-24 12:21:57.305030+0800 Test_copy_mutableCopy[1003:610433] blk0_for_reading-1<NSThread: 0x174073fc0>{number = 4, name = (null)}
2017-10-24 12:21:57.305121+0800 Test_copy_mutableCopy[1003:610433] blk3_for_reading-1<NSThread: 0x174073fc0>{number = 4, name = (null)}
2017-10-24 12:21:57.304973+0800 Test_copy_mutableCopy[1003:610435] blk2_for_reading-1<NSThread: 0x170272e80>{number = 5, name = (null)}
2017-10-24 12:21:57.305301+0800 Test_copy_mutableCopy[1003:610435] ---------blk4_for_writing-2<NSThread: 0x170272e80>{number = 5, name = (null)}
2017-10-24 12:21:57.305389+0800 Test_copy_mutableCopy[1003:610435] blk5_for_reading-2<NSThread: 0x170272e80>{number = 5, name = (null)}
2017-10-24 12:21:57.305460+0800 Test_copy_mutableCopy[1003:610435] blk6_for_reading-2<NSThread: 0x170272e80>{number = 5, name = (null)}
2017-10-24 12:21:57.305529+0800 Test_copy_mutableCopy[1003:610435] blk7_for_reading-2<NSThread: 0x170272e80>{number = 5, name = (null)}
2017-10-24 12:21:57.305598+0800 Test_copy_mutableCopy[1003:610433] blk8_for_reading-2<NSThread: 0x174073fc0>{number = 4, name = (null)}

5.死鎖的產(chǎn)生

必然引起死鎖的兩種方式

  • 主隊(duì)列 + 同步函數(shù)
      NSInteger count = 3;
      dispatch_queue_t mainQueue = dispatch_get_main_queue();
      dispatch_sync(mainQueue, ^{NSLog(@"mainQueue-%li%@", count,[NSThread currentThread]);});
    // result: 并沒(méi)有出現(xiàn)結(jié)果,因?yàn)橐呀?jīng)發(fā)生了死鎖
    
  • 串行隊(duì)列 + 異步函數(shù)的block內(nèi)部是(該串行隊(duì)列 + 同步函數(shù))(將串行隊(duì)列換成主隊(duì)列依然成立)
    dispatch_queue_t serialQueue = dispatch_queue_create("com.nextapp.qiannong", NULL);
      dispatch_async(serialQueue, ^{
          dispatch_sync(serialQueue, ^{NSLog(@"no deadLock");});
      });
    // result: 并沒(méi)有出現(xiàn)結(jié)果,因?yàn)橐呀?jīng)發(fā)生了死鎖
    

6.dispatch_apply

  • dispatch_apply 與dispatch_sync 函數(shù)類(lèi)似(dispatch_group_async, dispatch_group_notify, dispatch_group_wait),會(huì)等待處理執(zhí)行結(jié)束,在向下執(zhí)行;

  • dispatch_group_async 沒(méi)有執(zhí)行次數(shù)的要求

  • dispatch_apply 必須有執(zhí)行的次數(shù)

  • dispatch_barrier_async ,用于前后都有讀取異步任務(wù),中間有一個(gè)寫(xiě)操作

    // 建議在dispatch_async中異步執(zhí)行dispatch_apply函數(shù)
    
      dispatch_async(globalQueue, ^{
          dispatch_apply(10, globalQueue, ^(size_t index) {
              NSLog(@"%li-%@", index,[NSThread currentThread]);
          });
          dispatch_async(dispatch_get_main_queue(), ^{
              // 執(zhí)行更新界面的操作
              NSLog(@"Done-%@", [NSThread currentThread]);
          });
      });
    
      // 試驗(yàn)之后,并沒(méi)有生效
      dispatch_suspend(globalQueue); // 掛起
      dispatch_resume(globalQueue);  // 恢復(fù)
    

7.信號(hào)量機(jī)制相關(guān)

  • 相比串行隊(duì)列 和 柵欄函數(shù) ,力度更小;
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 保證可訪問(wèn)NSMutableArray類(lèi)對(duì)象的線程只能有1個(gè)
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    
    NSMutableArray *array = [NSMutableArray array];
    for (int idx = 0; idx < 10000; idx ++) {
        dispatch_async(globalQueue, ^{
 
           // 一直等到執(zhí)行semaphore的是計(jì)數(shù)值>=1.
           //          long result = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
          //            if (result == 0) {
          //            }else {
          //            }
            
            [array addObject:[NSNumber numberWithInt:idx]];
            
            // 執(zhí)行結(jié)束之后,釋放該鎖, 將dsemaphore的值 + 1;
            dispatch_semaphore_signal(semaphore);
        });
    }
    
    NSLog(@"%@", array);
    dispatch_release(semaphore);

8.單例

  • 在程序中,只執(zhí)行一次
  // 之前的初始化操作
    static BOOL initialized = NO;
    if (initialized == NO) {
        
        /*
         * 初始化操作
         */
        
        initialized = YES;
    }

  // 多線程環(huán)境下更加的安全
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        /*
         * 初始化操作
         */
    });

9.簡(jiǎn)記

線程

  • dispatch_sync/async:同步/異步是否開(kāi)啟新線程
  • 異步不阻塞當(dāng)前線程,同步阻塞當(dāng)前線程
  • serial/concurrent queue:串行/并行決定開(kāi)啟線程的條數(shù)

死鎖

  • 同步的在當(dāng)前隊(duì)列中(串行)中添加任務(wù)
  • 主隊(duì)列也是串行隊(duì)列
  • 相互阻塞構(gòu)成死鎖

信號(hào)量(semaphore)

  • 信號(hào)量是同步的(同步會(huì)阻塞當(dāng)前線程)
  • semaphore.create(p): p >= 0
  • semaphore.wait(): p <= 0, 阻塞當(dāng)前線程, p -= 1
  • semaphore.signal(): p += 1

group

  • 實(shí)現(xiàn)多個(gè)網(wǎng)絡(luò)的異步請(qǐng)求,最后再同步執(zhí)行任務(wù)
  • group.enter(), group.leave(), group.notify()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,263評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,946評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,708評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,409評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,774評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,641評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,872評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,650評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

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