久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

五個案例讓你明白GCD死鎖

 嘆落花 2015-10-19

作者:brighttj(@saitjr

網(wǎng)址:http://www./ios/ios-gcd-deadlock.html


死鎖一直都是在使用多線程時,,需要注意的一個問題。以前對同步,、異步,,串行、并行只有一個模糊的概念,,想想也是時候整理一下了,。再看看之前的博客,,已經(jīng)很久沒有干貨了【說得好像之前有干貨一樣】,所以,,這篇博客,,我盡最大努力,也借鑒了很多其他博客中的例子,,來講解GCD死鎖問題,。


環(huán)境信息:

Mac OS X 10.10.5

Xcode 6.4

iOS 8.4


串行與并行


在使用GCD的時候,我們會把需要處理的任務放到Block中,,然后將任務追加到相應的隊列里面,,這個隊列,叫做Dispatch Queue,。然而,存在于兩種Dispatch Queue,,一種是要等待上一個執(zhí)行完,,再執(zhí)行下一個的Serial Dispatch Queue,這叫做串行隊列,;另一種,,則是不需要上一個執(zhí)行完,就能執(zhí)行下一個的Concurrent Dispatch Queue,,叫做并行隊列,。這兩種,均遵循FIFO原則,。


舉一個簡單的例子,,在三個任務中輸出1、2,、3,,串行隊列輸出是有序的1、2,、3,,但是并行隊列的先后順序就不一定了。


那么,,并行隊列又是怎么在執(zhí)行呢,?


雖然可以同時多個任務的處理,但是并行隊列的處理量,,還是要根據(jù)當前系統(tǒng)狀態(tài)來,。如果當前系統(tǒng)狀態(tài)最多處理2個任務,那么1,、2會排在前面,,3什么時候操作,就看1或者2誰先完成,然后3接在后面,。


串行和并行就簡單說到這里,,關(guān)于它們的技術(shù)點其實還有很多,可以自行了解,。


同步與異步


串行與并行針對的是隊列,,而同步與異步,針對的則是線程,。最大的區(qū)別在于,,同步線程要阻塞當前線程,必須要等待同步線程中的任務執(zhí)行完,,返回以后,,才能繼續(xù)執(zhí)行下一任務;而異步線程則是不用等待,。


僅憑這幾句話還是很難理解,,所以之后準備了很多案例,可以邊分析邊理解,。


GCD API


GCD API很多,,這里僅介紹本文用到的。


1. 系統(tǒng)標準提供的兩個隊列


// 全局隊列,,也是一個并行隊列

dispatch_get_global_queue

// 主隊列,,在主線程中運行,因為主線程只有一個,,所以這是一個串行隊列

dispatch_get_main_queue


2. 除此之外,,還可以自己生成隊列


// 從DISPATCH_QUEUE_SERIAL看出,這是串行隊列

dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL)

// 同理,,這是一個并行隊列

dispatch_queue_create("com.demo.concurrentQueue", DISPATCH_QUEUE_CONCURRENT)


接下來是同步與異步線程的創(chuàng)建:


dispatch_sync(..., ^(block)) // 同步線程

dispatch_async(..., ^(block)) // 異步線程


案例與分析


假設你已經(jīng)基本了解了上面提到的知識,,接下來進入案例講解階段。


案例一:


NSLog(@"1"); // 任務1

dispatch_sync(dispatch_get_main_queue(), ^{

NSLog(@"2"); // 任務2

});

NSLog(@"3"); // 任務3


結(jié)果,,控制臺輸出:


1


分析:


  1. dispatch_sync表示是一個同步線程,;

  2. dispatch_get_main_queue表示運行在主線程中的主隊列;

  3. 任務2是同步線程的任務,。


首先執(zhí)行任務1,,這是肯定沒問題的,只是接下來,,程序遇到了同步線程,,那么它會進入等待,等待任務2執(zhí)行完,,然后執(zhí)行任務3,。但這是隊列,,有任務來,當然會將任務加到隊尾,,然后遵循FIFO原則執(zhí)行任務,。那么,現(xiàn)在任務2就會被加到最后,,任務3排在了任務2前面,,問題來了:


任務3要等任務2執(zhí)行完才能執(zhí)行,任務2由排在任務3后面,,意味著任務2要在任務3執(zhí)行完才能執(zhí)行,,所以他們進入了互相等待的局面?!炯热贿@樣,,那干脆就卡在這里吧】這就是死鎖。

案例二:


NSLog(@"1"); // 任務1

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

NSLog(@"2"); // 任務2

});

NSLog(@"3"); // 任務3


結(jié)果,,控制臺輸出:


1

2

3


分析:


首先執(zhí)行任務1,,接下來會遇到一個同步線程,程序會進入等待,。等待任務2執(zhí)行完成以后,才能繼續(xù)執(zhí)行任務3,。從dispatch_get_global_queue可以看出,,任務2被加入到了全局的并行隊列中,當并行隊列執(zhí)行完任務2以后,,返回到主隊列,,繼續(xù)執(zhí)行任務3。

案例三:


dispatch_queue_t queue = dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL);

NSLog(@"1"); // 任務1

dispatch_async(queue, ^{

NSLog(@"2"); // 任務2

dispatch_sync(queue, ^{

NSLog(@"3"); // 任務3

});

NSLog(@"4"); // 任務4

});

NSLog(@"5"); // 任務5


結(jié)果,,控制臺輸出:


1

5

2

// 5和2的順序不一定


分析:


這個案例沒有使用系統(tǒng)提供的串行或并行隊列,,而是自己通過dispatch_queue_create函數(shù)創(chuàng)建了一個DISPATCH_QUEUE_SERIAL的串行隊列。


  1. 執(zhí)行任務1,;

  2. 遇到異步線程,,將【任務2、同步線程,、任務4】加入串行隊列中,。因為是異步線程,所以在主線程中的任務5不必等待異步線程中的所有任務完成,;

  3. 因為任務5不必等待,,所以2和5的輸出順序不能確定;

  4. 任務2執(zhí)行完以后,,遇到同步線程,,這時,,將任務3加入串行隊列;

  5. 又因為任務4比任務3早加入串行隊列,,所以,,任務3要等待任務4完成以后,才能執(zhí)行,。但是任務3所在的同步線程會阻塞,,所以任務4必須等任務3執(zhí)行完以后再執(zhí)行。這就又陷入了無限的等待中,,造成死鎖,。


案例四:


NSLog(@"1"); // 任務1

dispatch_async(dispatch_get_global_queue(0, 0), ^{

NSLog(@"2"); // 任務2

dispatch_sync(dispatch_get_main_queue(), ^{

NSLog(@"3"); // 任務3

});

NSLog(@"4"); // 任務4

});

NSLog(@"5"); // 任務5


結(jié)果,控制臺輸出:


1

2

5

3

4

// 5和2的順序不一定


分析:


首先,,將【任務1,、異步線程、任務5】加入Main Queue中,,異步線程中的任務是:【任務2,、同步線程、任務4】,。


所以,,先執(zhí)行任務1,然后將異步線程中的任務加入到Global Queue中,,因為異步線程,,所以任務5不用等待,結(jié)果就是2和5的輸出順序不一定,。


然后再看異步線程中的任務執(zhí)行順序,。任務2執(zhí)行完以后,遇到同步線程,。將同步線程中的任務加入到Main Queue中,,這時加入的任務3在任務5的后面。


當任務3執(zhí)行完以后,,沒有了阻塞,,程序繼續(xù)執(zhí)行任務4。


從以上的分析來看,,得到的幾個結(jié)果:1最先執(zhí)行,;2和5順序不一定;4一定在3后面,。

案例五:


dispatch_async(dispatch_get_global_queue(0, 0), ^{

NSLog(@"1"); // 任務1

dispatch_sync(dispatch_get_main_queue(), ^{

NSLog(@"2"); // 任務2

});

NSLog(@"3"); // 任務3

});

NSLog(@"4"); // 任務4

while (1) {

}

NSLog(@"5"); // 任務5


結(jié)果,,控制臺輸出:


1

4

// 1和4的順序不一定


分析:


和上面幾個案例的分析類似,先來看看都有哪些任務加入了Main Queue:【異步線程,、任務4,、死循環(huán),、任務5】。


在加入到Global Queue異步線程中的任務有:【任務1,、同步線程,、任務3】。


第一個就是異步線程,,任務4不用等待,,所以結(jié)果任務1和任務4順序不一定。


任務4完成后,,程序進入死循環(huán),,Main Queue阻塞。但是加入到Global Queue的異步線程不受影響,,繼續(xù)執(zhí)行任務1后面的同步線程,。


同步線程中,將任務2加入到了主線程,,并且,,任務3等待任務2完成以后才能執(zhí)行。這時的主線程,,已經(jīng)被死循環(huán)阻塞了,。所以任務2無法執(zhí)行,當然任務3也無法執(zhí)行,,在死循環(huán)后的任務5也不會執(zhí)行,。


最終,只能得到1和4順序不定的結(jié)果,。

參考


http://www.jianshu.com/p/0b0d9b1f1f19

http://www.cnblogs.com/tangbinblog/p/4133481.html

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多