網(wǎng)上關(guān)于多線程的文章太多了,但是我發(fā)現(xiàn)好多存在不正確或者不規(guī)范的地方
參考文章鏈接
https://juejin.im/post/59c13d5cf265da0669085a52#heading-10
并行和并發(fā)
網(wǎng)上好多文章都混淆了并行和并發(fā)的概念,其實(shí)這兩者有本質(zhì)區(qū)別: 并行是真正的多線程,并發(fā)是偽多線程.
這里引用一下別人博客的截圖

同一時(shí)刻,一個(gè)CPU只能處理一個(gè)操作,只有多核CPU才能處理多個(gè)操作,也就是說(shuō)只有多核CPU才是并行的
我們平時(shí)開(kāi)發(fā)中,基本上都是并發(fā)
任務(wù) ,隊(duì)列, 線程
任務(wù):
即,operation,就是一段代碼塊,在 GCD 中就是一個(gè) Block
任務(wù)分兩種:同步執(zhí)行 任務(wù) 和 異步執(zhí)行任務(wù),
二者區(qū)別: 此任務(wù)是否會(huì)阻塞當(dāng)前線程(系統(tǒng)是否會(huì)為任務(wù)創(chuàng)建新的線程)
至于開(kāi)一條,還是開(kāi)多條線程,是由 任務(wù)和隊(duì)列 綜合因素決定的
隊(duì)列:
隊(duì)列是 保存 和 管理任務(wù)的;隊(duì)列本身是線程安全的.
隊(duì)列分為 串行隊(duì)列(serial) 和 并發(fā)隊(duì)列(concurrent),所有隊(duì)列都遵循FIFO(先進(jìn)先出)的原則;將任務(wù)加到隊(duì)列中,任務(wù)會(huì)按照加入到隊(duì)列中先后順序依次執(zhí)行。
注意:
1.在隊(duì)列中,任務(wù)的取出都是FIFO的,但是出了隊(duì)列任務(wù)的執(zhí)行就不一定了
2.放到串行隊(duì)列的任務(wù),GCD 會(huì) FIFO(先進(jìn)先出) 地取出來(lái)一個(gè),執(zhí)行一個(gè),然后取下一個(gè),這樣一個(gè)一個(gè)的執(zhí)行
3.放到并發(fā)隊(duì)列的任務(wù),GCD 也會(huì) FIFO的取出來(lái)(也就是說(shuō),它也是偽并行的,同一時(shí)刻它也只能取出一個(gè)任務(wù))
但不同的是,它取出來(lái)一個(gè)就會(huì)放到別的線程,然后再取出來(lái)一個(gè)又放到另一個(gè)的線程。這樣由于取的動(dòng)作很快,忽略不計(jì),看起來(lái),所有的任務(wù)都是一起取出的。
不過(guò)需要注意,GCD 會(huì)根據(jù)系統(tǒng)資源控制并行的數(shù)量,所以如果任務(wù)很多,它并不會(huì)讓所有任務(wù)同時(shí)取出.
線程:
線程的創(chuàng)建、維護(hù)和銷毀由操作系統(tǒng)管理的
如何分析 線程和任務(wù)的執(zhí)行情況
先看任務(wù)是阻塞還是非阻塞,在看對(duì)列是串行還是并發(fā)的
任務(wù)和隊(duì)列排列組合有四種情況
1.同步任務(wù),串行隊(duì)列
這里要注意很容易造成死鎖,例如
- (void)viewDidAppear:(BOOL)animated {
dispatch_sync(dispatch_get_main_queue(), ^(void){
NSLog(@"這里死鎖了");
});
}

新版XCode編譯器直接報(bào)錯(cuò)了,來(lái)分析一下原因:
viewDidAppear這個(gè)方法是在主線程運(yùn)行的,方法里block是個(gè)是個(gè)同步任務(wù)會(huì)阻塞當(dāng)前線程,主線程是存放在主隊(duì)列中,block也是在主隊(duì)列中,由于是同步任務(wù)當(dāng)程序執(zhí)行到這個(gè)block這行代碼時(shí)要立刻執(zhí)行這個(gè)block,但是由于是在串行隊(duì)列中,任務(wù)是一個(gè)一個(gè)取出的,viewDidAppear函數(shù)還沒(méi)有返回,所以這個(gè)block是不會(huì)從對(duì)列取出的,所以就造成死鎖了