09 - OC多線程之隊(duì)列任務(wù)以及死鎖的認(rèn)識(shí)

OC底層原理探索文檔匯總

主要內(nèi)容:

1危纫、隊(duì)列的認(rèn)識(shí)
2虫溜、任務(wù)的認(rèn)識(shí)
3、隊(duì)列和任務(wù)搭配使用的面試題
4耙厚、死鎖的認(rèn)識(shí)和解決

隊(duì)列

隊(duì)列就是管理待執(zhí)行任務(wù)的等待隊(duì)列渠缕,用來(lái)調(diào)度任務(wù)給線程執(zhí)行勾哩,符合先進(jìn)先出原則

并發(fā)和串行決定了任務(wù)執(zhí)行的順序股耽,并發(fā)是多個(gè)任務(wù)并發(fā)執(zhí)行根盒,串行是指任務(wù)順序執(zhí)行,也就是一個(gè)任務(wù)執(zhí)行完成再執(zhí)行下一個(gè)任務(wù)

  • 隊(duì)列負(fù)責(zé)調(diào)度任務(wù)物蝙,提交任務(wù)給線程執(zhí)行
  • 隊(duì)列遵循先進(jìn)先出原則,在這里指的是先進(jìn)先調(diào)度敢艰。而不是先調(diào)度完成诬乞。
  • 隊(duì)列底層會(huì)維護(hù)一個(gè)線程池來(lái)處理用戶提交的任務(wù),線程池的作用就是執(zhí)行隊(duì)列管理的任務(wù)钠导。
  • 串行隊(duì)列底層只維護(hù)了一個(gè)線程震嫉,并發(fā)隊(duì)列的底層維護(hù)了多個(gè)線程
  • 串行隊(duì)列一次只能處理一個(gè)任務(wù),上一個(gè)任務(wù)處理完成才能處理下一個(gè)任務(wù)
  • 并發(fā)隊(duì)列可以同時(shí)處理多個(gè)任務(wù)牡属,雖然處理順序還是先進(jìn)先出的原則票堵,但是有的任務(wù)處理時(shí)間比較長(zhǎng),有可能先進(jìn)后調(diào)度完成逮栅。
  • 隊(duì)列是先進(jìn)先調(diào)度悴势,如果是串行隊(duì)列是先進(jìn)先調(diào)度結(jié)束,并發(fā)隊(duì)列并不是先進(jìn)先調(diào)度結(jié)束措伐,可以同時(shí)調(diào)度多個(gè)任務(wù)

創(chuàng)建隊(duì)列:

- (void)createQueueTest{
    //創(chuàng)建隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("串行隊(duì)列", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create("并發(fā)隊(duì)列", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t queue3 = dispatch_queue_create("串行隊(duì)列", NULL);
    //獲取已有隊(duì)列
    //獲取主隊(duì)列
    dispatch_queue_t queue4 = dispatch_get_main_queue();
    //獲取全局并發(fā)隊(duì)列
    /*
     第一個(gè)參數(shù)是優(yōu)先級(jí)特纤,第二個(gè)無(wú)意義,填0
     */
    dispatch_queue_t queue5 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
}

任務(wù)

任務(wù)就是線程要執(zhí)行的那段代碼
執(zhí)行任務(wù)有兩種方式侥加,同步和異步捧存,同步和可以異步?jīng)Q定是否要開(kāi)啟新的線程,同步不開(kāi)啟担败,異步開(kāi)啟昔穴。

同步函數(shù)(sync):

  • 同步函數(shù)用來(lái)實(shí)現(xiàn)線程同步執(zhí)行任務(wù)
  • 只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開(kāi)啟新線程的能力
  • 同步函數(shù)只能等block執(zhí)行完成后才能返回

異步函數(shù)(async):

  • 異步函數(shù)用來(lái)實(shí)現(xiàn)線程異步執(zhí)行任務(wù)
  • 異步函數(shù)不需要等block執(zhí)行完成后就可以返回
  • 可以開(kāi)啟新線程

提交任務(wù)的函數(shù)很多都有兩個(gè)版本提前,一個(gè)是傳兩個(gè)參數(shù)吗货,傳遞作為任務(wù)的block代碼,一個(gè)是傳三個(gè)參數(shù)岖研,傳遞作為任務(wù)的方法卿操。

- (void)createTaskTest{
    /*
     參數(shù)一:隊(duì)列
     參數(shù)二:作為任務(wù)的block代碼
     */
     //在調(diào)度隊(duì)列上提交異步執(zhí)行的塊并立即返回
    dispatch_async(dispatch_queue_t  _Nonnull queue, <#^(void)block#>);
    /*
     參數(shù)一:隊(duì)列
     參數(shù)二:上下文
     參數(shù)三:作為任務(wù)的函數(shù)
     */
    dispatch_async_f(<#dispatch_queue_t  _Nonnull queue#>, <#void * _Nullable context#>, <#dispatch_function_t  _Nonnull work#>);
    
    /*
     參數(shù)一:隊(duì)列
     參數(shù)二:作為任務(wù)的block代碼
     */
     //提交塊對(duì)象以執(zhí)行,并在該塊完成執(zhí)行后返回孙援。 
    dispatch_sync(dispatch_queue_t  _Nonnull queue, <#^(void)block#>);
    /*
     參數(shù)一:隊(duì)列
     參數(shù)二:上下文
     參數(shù)三:作為任務(wù)的函數(shù)
     */
    dispatch_sync_f(<#dispatch_queue_t  _Nonnull queue#>, <#void * _Nullable context#>, <#dispatch_function_t  _Nonnull work#>);
}

注意:

  • 任務(wù)是線程執(zhí)行的害淤,不是隊(duì)列執(zhí)行,隊(duì)列只是用來(lái)調(diào)度任務(wù)的
  • 任務(wù)的執(zhí)行方式有同步和異步拓售,同步不開(kāi)辟新線程窥摄,異步會(huì)開(kāi)辟新線程

主隊(duì)列

主隊(duì)列是一種特殊的串行隊(duì)列,特殊在于只使用在主線程和主Runloop中础淤,并且是在啟動(dòng)APP時(shí)自動(dòng)創(chuàng)建的崭放。
主隊(duì)列是指主線程的隊(duì)列哨苛,是一個(gè)串行隊(duì)列,在主線程去執(zhí)行其實(shí)就是放入了主隊(duì)列

全局并發(fā)隊(duì)列

全局并發(fā)隊(duì)列是系統(tǒng)提供的币砂,開(kāi)發(fā)者可以直接使用的一個(gè)并發(fā)隊(duì)列建峭,沒(méi)有其他的特殊之處。

在獲取時(shí)可以給定優(yōu)先級(jí)

  • DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED
  • DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT
  • DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND

總結(jié)

任務(wù)隊(duì)列線程的關(guān)系.png
  • 線程有兩種方式執(zhí)行任務(wù)决摧,同步和異步亿蒸,分別通過(guò)同步函數(shù)和異步函數(shù)來(lái)實(shí)現(xiàn)
  • 同步函數(shù)添加的任務(wù),該線程執(zhí)行完這個(gè)任務(wù)才可以執(zhí)行其他任務(wù)掌桩,異步函數(shù)添加的任務(wù)边锁,線程可以并發(fā)執(zhí)行該任務(wù)
  • 任務(wù)存放在隊(duì)列中,隊(duì)列有兩種調(diào)度方式波岛,串行和并發(fā)茅坛,串行只能順序處理任務(wù),并發(fā)可以同時(shí)處理多個(gè)任務(wù)
  • 線程想要并發(fā)執(zhí)行任務(wù)则拷,需要異步函數(shù)添加任務(wù)給并發(fā)隊(duì)列
  • 如果隊(duì)列是串行的贡蓖,即使線程可以并發(fā)執(zhí)行任務(wù)也不行,因?yàn)殛?duì)列是串行調(diào)度給線程的隔躲。
  • 同步函數(shù)需要等待block執(zhí)行完成才可以返回
  • 異步函數(shù)不需要等待block執(zhí)行完成就可以返回

隊(duì)列和任務(wù)的搭配使用

任務(wù)和隊(duì)列以及線程的執(zhí)行關(guān)系.png

說(shuō)明:

  • 同步不開(kāi)啟新線程摩梧,異步會(huì)開(kāi)啟新線程
  • 并發(fā)隊(duì)列可以并發(fā)調(diào)度任務(wù),串行隊(duì)列只能順序調(diào)度任務(wù)
  • 只有并發(fā)隊(duì)列提交給線程異步執(zhí)行的任務(wù)才可以異步執(zhí)行

總結(jié):

執(zhí)行類型.png

隊(duì)列和任務(wù)的常見(jiàn)類型代碼演示

1宣旱、基礎(chǔ)寫法

給一個(gè)串行隊(duì)列添加了一個(gè)任務(wù)仅父,該任務(wù)需要異步執(zhí)行

- (void)syncTest{
    // 把任務(wù)添加到隊(duì)列 --> 函數(shù)
    // 任務(wù) _t ref c對(duì)象
    dispatch_block_t block = ^{
        NSLog(@"hello GCD");
    };
    //串行隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("wy", NULL);
    // 函數(shù)
    dispatch_async(queue, block);
    
}

2、主隊(duì)列同步

- (void)mainSyncTest{
    
    NSLog(@"0");
    // 等
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"1");
    });
    NSLog(@"2");
}

執(zhí)行結(jié)果: 0浑吟,之后死鎖

死鎖.png

說(shuō)明:

  • 在主隊(duì)列中添加了三個(gè)任務(wù)笙纤,任務(wù)0,同步任務(wù)塊组力,任務(wù)2
  • 同步任務(wù)塊的任務(wù)本身就是給主隊(duì)列添加了任務(wù)1
  • 因此現(xiàn)在主隊(duì)列的任務(wù)有四個(gè)省容,并且順序?yàn)槿蝿?wù)0、同步任務(wù)塊燎字、任務(wù)2腥椒、任務(wù)1,這幾個(gè)任務(wù)依次執(zhí)行
  • 同步任務(wù)塊需要等待任務(wù)1的完成才能返回候衍,但是任務(wù)1的完成又在同步任務(wù)塊的后面
  • 所以造成了同步任務(wù)塊和任務(wù)1的相互等待笼蛛,死鎖導(dǎo)致程序崩潰

注意:造成死鎖是同步任務(wù)塊和任務(wù)1的相互等待,與任務(wù)2沒(méi)關(guān)系蛉鹿,就算刪掉任務(wù)2滨砍,也會(huì)死鎖

3、 主隊(duì)列異步

- (void)mainAsyncTest{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"1");
    });
    NSLog(@"2");
}

執(zhí)行結(jié)果: 21
說(shuō)明:

  • 主隊(duì)列中添加兩個(gè)任務(wù),異步任務(wù)塊和任務(wù)2
  • 異步任務(wù)塊的任務(wù)本身是給主隊(duì)列添加了一個(gè)任務(wù)1
  • 這樣主隊(duì)列有三個(gè)任務(wù)惋戏,并且順序?yàn)楫惒饺蝿?wù)塊领追、任務(wù)2、任務(wù)1
  • 因?yàn)槿蝿?wù)1是異步提交的响逢,也就是線程以異步的方式來(lái)執(zhí)行绒窑,異步任務(wù)塊不需要等block執(zhí)行完成就可以返回
  • 因此這里不會(huì)發(fā)生死鎖

4、 全局并發(fā)隊(duì)列異步

并發(fā)執(zhí)行任務(wù)

- (void)globalAsyncTest{
    
    for (int i = 0; i<20; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }
    NSLog(@"hello queue");
}

結(jié)果:

2021-10-31 14:58:16.038522+0800 多線程使用[11062:5684222] hello queue
2021-10-31 14:58:16.038559+0800 多線程使用[11062:5684360] 0-<NSThread: 0x600003d438c0>{number = 6, name = (null)}
2021-10-31 14:58:16.038564+0800 多線程使用[11062:5684368] 2-<NSThread: 0x600003d34440>{number = 7, name = (null)}
2021-10-31 14:58:16.038567+0800 多線程使用[11062:5684359] 3-<NSThread: 0x600003d28780>{number = 4, name = (null)}
2021-10-31 14:58:16.038571+0800 多線程使用[11062:5684358] 1-<NSThread: 0x600003d282c0>{number = 8, name = (null)}
2021-10-31 14:58:16.038585+0800 多線程使用[11062:5684361] 4-<NSThread: 0x600003d31b80>{number = 3, name = (null)}
2021-10-31 14:58:16.038606+0800 多線程使用[11062:5684362] 5-<NSThread: 0x600003d43e00>{number = 5, name = (null)}
2021-10-31 14:58:16.038642+0800 多線程使用[11062:5684360] 7-<NSThread: 0x600003d438c0>{number = 6, name = (null)}

說(shuō)明:

  • 異步執(zhí)行會(huì)開(kāi)啟新線程舔亭,因此有多個(gè)線程來(lái)執(zhí)行
  • 在并發(fā)隊(duì)列中異步執(zhí)行代碼塊回论,因此執(zhí)行順序是異步的
  • 并且打印hello是最早執(zhí)行的,這是因?yàn)楫惒讲l(fā)執(zhí)行分歇,異步添加任務(wù)消耗的時(shí)間比較多,所以先執(zhí)行hello

5欧漱、 全局并發(fā)隊(duì)列同步

串行執(zhí)行任務(wù)

- (void)globalSyncTest{
    for (int i = 0; i<20; i++) {
        dispatch_sync(dispatch_get_global_queue(0, 0), ^{
            NSLog(@"%d-%@",i,[NSThread currentThread]);
        });
    }
    NSLog(@"hello queue");
}

結(jié)果:

2021-10-31 14:55:53.552472+0800 多線程使用[10971:5681912] 13-<_NSMainThread: 0x600000a2c7c0>{number = 1, name = main}
2021-10-31 14:55:53.552541+0800 多線程使用[10971:5681912] 14-<_NSMainThread: 0x600000a2c7c0>{number = 1, name = main}
2021-10-31 14:55:53.552635+0800 多線程使用[10971:5681912] 15-<_NSMainThread: 0x600000a2c7c0>{number = 1, name = main}
2021-10-31 14:55:53.552729+0800 多線程使用[10971:5681912] 16-<_NSMainThread: 0x600000a2c7c0>{number = 1, name = main}
2021-10-31 14:55:53.552829+0800 多線程使用[10971:5681912] 17-<_NSMainThread: 0x600000a2c7c0>{number = 1, name = main}
2021-10-31 14:55:53.559220+0800 多線程使用[10971:5681912] 18-<_NSMainThread: 0x600000a2c7c0>{number = 1, name = main}
2021-10-31 14:55:53.559332+0800 多線程使用[10971:5681912] 19-<_NSMainThread: 0x600000a2c7c0>{number = 1, name = main}
2021-10-31 14:55:53.559401+0800 多線程使用[10971:5681912] hello queue

說(shuō)明:

  • 主隊(duì)列中有同步任務(wù)塊和hello兩個(gè)任務(wù)职抡,同步任務(wù)塊添加了多個(gè)任務(wù)到并發(fā)隊(duì)列中
  • 因?yàn)槭峭胶瘮?shù),所以不會(huì)開(kāi)啟新線程误甚,只有一個(gè)主線程來(lái)執(zhí)行
  • 并且打印hello是在最后執(zhí)行的缚甩,這是因?yàn)橥酱a塊是在hello任務(wù)的前面,同步函數(shù)需要等代碼塊執(zhí)行完成后再返回窑邦,所以需要等同步代碼塊執(zhí)行完才能執(zhí)行hello

簡(jiǎn)單面試題分析

面試題1

- (void)textDemo1{
    
    dispatch_queue_t queue = dispatch_queue_create("cooci", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");

}

結(jié)果: 15243

說(shuō)明:

  • 在主隊(duì)列中包含三個(gè)任務(wù)擅威,同步任務(wù)1、異步任務(wù)代碼塊冈钦、同步任務(wù)5
  • 異步任務(wù)塊不需要等待函數(shù)執(zhí)行完成就可以返回郊丛,而異步函數(shù)本身是耗時(shí)的,所以前面的順序是1瞧筛、5
  • 在異步任務(wù)中將三個(gè)任務(wù)添加到一個(gè)并發(fā)隊(duì)列中厉熟,包括任務(wù)2,同步代碼塊较幌、任務(wù)4
  • 因?yàn)槭遣l(fā)隊(duì)列異步提交任務(wù)揍瑟,所以這三個(gè)任務(wù)并發(fā)執(zhí)行,
  • 但因?yàn)殛?duì)列的先進(jìn)先出原則乍炉,先進(jìn)的先調(diào)用绢片,再看消耗的時(shí)間,同步代碼塊會(huì)消耗更多的時(shí)間岛琼,所以最后執(zhí)行
  • 任務(wù)2和任務(wù)4執(zhí)行時(shí)間一樣底循,但是任務(wù)2先執(zhí)行
  • 所以順序?yàn)?、4衷恭、3此叠,合起來(lái)就是15243

面試題2

- (void)textDemo{
    
    dispatch_queue_t queue = dispatch_queue_create("cooci", NULL);
    NSLog(@"1");
    // 耗時(shí)
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}

結(jié)果: 1、5、2灭袁,崩潰

20-面試題解析2.png

說(shuō)明:

  • 在主隊(duì)列中包含三個(gè)任務(wù)猬错,同步任務(wù)1、異步任務(wù)代碼塊茸歧、同步任務(wù)5
  • 主隊(duì)列是串行的倦炒,所以調(diào)度順序是任務(wù)1、代碼塊软瞎、任務(wù)5
  • 異步任務(wù)塊不需要等block執(zhí)行完就可以返回逢唤,所以順序是1、5
  • 代碼塊中將三個(gè)任務(wù)添加到一個(gè)并發(fā)隊(duì)列中涤浇,包括任務(wù)2鳖藕,同步代碼塊、任務(wù)4
  • 在串行隊(duì)列中只锭,包含任務(wù)2和同步任務(wù)塊著恩、任務(wù)4、任務(wù)3蜻展,而同步任務(wù)塊的執(zhí)行結(jié)束需要等待任務(wù)3的結(jié)束
  • 造成死鎖喉誊,因此在執(zhí)行完3后會(huì)崩潰

注意:
這里雖然是主隊(duì)列,任務(wù)塊在任務(wù)5的前面纵顾,但是在執(zhí)行時(shí)我們看到先執(zhí)行了任務(wù)5后執(zhí)行了任務(wù)2伍茄,
這是因?yàn)楫惒讲僮鞑⒉恍枰却瘮?shù)的執(zhí)行完成而完成,

面試題3

- (void)wbinterDemo{
    dispatch_queue_t queue11 = dispatch_queue_create("wy", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue11, ^{
        NSLog(@"1");
    });
    dispatch_async(queue11, ^{
        NSLog(@"2");
    });
    dispatch_sync(queue11, ^{
        NSLog(@"3");
    });
    NSLog(@"0");
    dispatch_async(queue11, ^{
        NSLog(@"1");
    });
    dispatch_async(queue11, ^{
        NSLog(@"7");
    });
    dispatch_async(queue11, ^{
        NSLog(@"8");
    });
    dispatch_async(queue11, ^{
        NSLog(@"9");
    }); 
}

請(qǐng)選擇:
A:1230789
B:1237890
C:3120798
D:2137890

答案為AC

說(shuō)明:

  • 首先這些任務(wù)塊操作都是在主隊(duì)列中施逾,其中任務(wù)3不會(huì)開(kāi)啟新線程敷矫,和任務(wù)0都是主線程執(zhí)行的,其他的任務(wù)在并發(fā)隊(duì)列中音念,會(huì)開(kāi)啟新線程執(zhí)行沪饺,同步任務(wù)塊必須等任務(wù)3執(zhí)行完才能繼續(xù)往下執(zhí)行,所以任務(wù)3肯定在任務(wù)0前面闷愤。(簡(jiǎn)單認(rèn)識(shí)整葡,同步并發(fā)是串行,所以任務(wù)3在任務(wù)0前面)
  • 7讥脐、8遭居、9任務(wù)在任務(wù)0后添加,所以會(huì)在0任務(wù)后面執(zhí)行
  • 同時(shí)7旬渠、8俱萍、9任務(wù)都是異步并發(fā),所以并發(fā)執(zhí)行告丢,沒(méi)有順序
  • 任務(wù)1枪蘑、2在任務(wù)3之前添加到并發(fā)隊(duì)列中,也就是任務(wù)1和2與3在不同的隊(duì)列中,而任務(wù)1和2又是異步并發(fā)的岳颇,所以他們?nèi)齻€(gè)會(huì)異步并發(fā)執(zhí)行照捡,他們?nèi)齻€(gè)是沒(méi)有順序的。

死鎖的認(rèn)識(shí)

死鎖就是同一個(gè)串行隊(duì)列中兩個(gè)任務(wù)相互等待引起死鎖.

網(wǎng)上面很多說(shuō)是不同的線程相互等待引起的话侧,是解釋不通的栗精,應(yīng)該是隊(duì)列,因?yàn)殛?duì)列是先進(jìn)先出原則導(dǎo)致瞻鹏,而后面進(jìn)入的任務(wù)的結(jié)束又依賴于前面進(jìn)的任務(wù)悲立。
一個(gè)串行隊(duì)列的線程池只維護(hù)了一個(gè)線程。

死鎖的場(chǎng)景

主隊(duì)列同步執(zhí)行

- (void)viewDidLoad {
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"任務(wù)1");
});
}

說(shuō)明:

  • 在主隊(duì)列中有同步任務(wù)塊新博,之后添加任務(wù)1到主隊(duì)列中薪夕。
  • 而同步任務(wù)塊的執(zhí)行完成需要等block執(zhí)行完成,所以同步任務(wù)塊的執(zhí)行依賴于任務(wù)1
  • 而在串行隊(duì)列中赫悄,任務(wù)1的完成又需要同步任務(wù)塊的完成寥殖。
  • 由此同步任務(wù)塊和任務(wù)1相互等待,造成了死鎖

同步串行隊(duì)列的嵌套場(chǎng)景也是一樣的涩蜘,不再多言

- (void)textDemo{
    
    dispatch_queue_t queue = dispatch_queue_create("cooci", NULL);
    NSLog(@"1");
    // 耗時(shí)
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_async(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}

死鎖的解決

上面知道死鎖是一個(gè)串行隊(duì)列中有兩個(gè)任務(wù)相互等待導(dǎo)致的,所以有兩個(gè)解決辦法熏纯,

  • 隊(duì)列為并發(fā)同诫,不是串行
  • 異步任務(wù),取消一方的等待樟澜,也就打破相互等待

所以可以有兩個(gè)做法误窖,

將隊(duì)列改為并發(fā)

- (void)textDemo1{
    
    dispatch_queue_t queue = dispatch_queue_create("cooci", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");

}

將任務(wù)改為異步任務(wù),及不會(huì)相互等待

- (void)textDemo{
    
    dispatch_queue_t queue = dispatch_queue_create("cooci", NULL);
    NSLog(@"1");
    // 耗時(shí)
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_async(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載秩贰,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者霹俺。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市毒费,隨后出現(xiàn)的幾起案子丙唧,更是在濱河造成了極大的恐慌,老刑警劉巖觅玻,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件想际,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡溪厘,警方通過(guò)查閱死者的電腦和手機(jī)胡本,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)畸悬,“玉大人侧甫,你說(shuō)我怎么就攤上這事。” “怎么了披粟?”我有些...
    開(kāi)封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵咒锻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我僻爽,道長(zhǎng)虫碉,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任胸梆,我火速辦了婚禮敦捧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碰镜。我一直安慰自己兢卵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布绪颖。 她就那樣靜靜地躺著秽荤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪柠横。 梳的紋絲不亂的頭發(fā)上窃款,一...
    開(kāi)封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音牍氛,去河邊找鬼晨继。 笑死,一個(gè)胖子當(dāng)著我的面吹牛搬俊,可吹牛的內(nèi)容都是我干的紊扬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼唉擂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼餐屎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起玩祟,我...
    開(kāi)封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤腹缩,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后空扎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體庆聘,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年勺卢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伙判。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡黑忱,死狀恐怖宴抚,靈堂內(nèi)的尸體忽然破棺而出勒魔,到底是詐尸還是另有隱情,我是刑警寧澤菇曲,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布冠绢,位于F島的核電站,受9級(jí)特大地震影響常潮,放射性物質(zhì)發(fā)生泄漏弟胀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一喊式、第九天 我趴在偏房一處隱蔽的房頂上張望孵户。 院中可真熱鬧,春花似錦岔留、人聲如沸夏哭。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)竖配。三九已至,卻和暖如春里逆,著一層夾襖步出監(jiān)牢的瞬間进胯,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工原押, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留龄减,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓班眯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親烁巫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子署隘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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