【iOS面試系列-2】多線程中同步、非同步和串列、並行之間的邏輯關係(必考,必須掌握),ios-2
API-https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/doc/uid/TP40008079
一、同步、非同步和串列、並行
任務串列執行就是每次只有一個任務被執行,任務並發執行就是在同一時間可以有多個任務被執行。
一個同步函數只在完成了它預定的任務後才返回。一個非同步函數,剛好相反,會立即返回,預定的任務會完成但不會等它完成。因此,一個非同步函數不會阻塞當前線程去執行下一個函數。 (來源:http://www.cocoachina.com/industry/20140428/8248.html)
隊列分為串列和並行
任務的執行分為同步和非同步
------- 隊列只是負責任務的調度,而不負責任務的執行 ---------
------- 任務是線上程中執行的 ---------
串列隊列:任務按照順序被調度,前一個任務不執行完畢,隊列不會調度
並行隊列:只要有閒置線程,隊列就會調度當前任務,交給線程去執行,不需要考慮前面是都有任務在執行,只要有線程可以利用,隊列就會調度任務。
同步執行:不會開啟新的線程,任務按順序執行
非同步執行:會開啟新的線程,任務可以並發的執行
(來源:http://www.cnblogs.com/KongPro/p/5193175.html)
【註:兩人說的有矛盾,一個說隊列執行任務,一個說隊列不執行任務= =一個說同步非同步是返回的問題,一個說同步非同步是開不開線程的問題】
同步(sync)
和
非同步(async)
的主要區別在於會不會阻塞當前線程,直到
Block
中的任務執行完畢!
如果是
同步(sync)
操作,它會阻塞當前線程並等待
Block
中的任務執行完畢,然後當前線程才會繼續往下運行。
如果是
非同步(async)
操作,當前線程會直接往下執行,它不會阻塞當前線程。 (原文連結:http://www.jianshu.com/p/0b0d9b1f1f19) 【第三個人和第一個人的意思差不多】
二、隊列
GCD 提供有 dispatch queues 來處理代碼塊,這些隊列管理你提供給 GCD 的任務並用 FIFO 順序執行這些任務。這就保證了第一個被添加到隊列裡的任務會是隊列中第一個開始的任務,而第二個被添加的任務將第二個開始,如此直到隊列的終點。
1、串列隊列
唯一能確保的事情是 GCD 一次只執行一個任務,並且按照我們添加到隊列的順序來執行。由於在串列隊列中不會有兩個任務並發運行。
放到串列隊列的任務,GCD 會 FIFO(先進先出)
地取出來一個,執行一個,然後取下一個,這樣一個一個的執行。
2、並發隊列
在並發隊列中的任務能得到的保證是它們會按照被添加的順序開始執行,任務可能以任意順序完成,你不會知道何時開始運行下一個任務,或者任意時刻有多少 Block 在運行。再說一遍,這完全取決於 GCD 。
放到並行隊列的任務,GCD 也會 FIFO
的取出來,但不同的是,它取出來一個就會放到別的線程,然後再取出來一個又放到另一個的線程。這樣由於取的動作很快,忽略不計,看起來,所有的任務都是一起執行的。不過需要注意,GCD 會根據系統資源控制並行的數量,所以如果任務很多,它並不會讓所有任務同時執行。
(來源:http://www.cocoachina.com/industry/20140428/8248.html)
(原文連結:http://www.jianshu.com/p/0b0d9b1f1f19)
三、組合
(來源:http://www.cnblogs.com/KongPro/p/5193175.html)
【個人總結:串列、並行區別就是有任務會不會放在別的線程
同步、非同步區別是會不會阻塞當前線程
串列同步:取出一個任務不放進別的線程,阻塞當前線程(不開闢新的線程),任務執行完畢,任務執行完畢,下一個任務
串列非同步:取出一個任務不放進別的線程,不阻塞當前線程,不等任務執行完成,任務執行完畢,下一個任務
並行同步:取出來一個任務可以放在別的線程,阻塞當前線程(不開闢新的線程),任務執行完畢,不等任務執行完畢,下一個任務
並行非同步:取出來一個任務可以放在別的線程,不阻塞當前線程,不等任務執行完成,不等任務執行完成,下一個任務
】
【所以現在最大的問題是,如果只有一個線程去非同步執行一個並行隊列裡的任務,會是怎樣?感覺上來說,不開線程的話就是同步,一旦叫非同步就說明開了線程,所以把這三個人的總結起來才比較合理】
let queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL) //建立串列隊列 NSLog("之前 - %@", NSThread.currentThread()) dispatch_async(queue, { () -> Void in //非同步執行串列隊列-開了一個新的線程 NSLog("sync之前 - %@", NSThread.currentThread()) dispatch_sync(queue, { () -> Void in //同步執行串列隊列-阻塞當前線程並等待上一個任務執行完畢(而上一個任務就是阻塞的這個) NSLog("sync - %@", NSThread.currentThread()) }) NSLog("sync之後 - %@", NSThread.currentThread()) }) NSLog("之後 - %@", NSThread.currentThread())
【部落格上找來的還是不放心,有時間在書上看到相關的我會再來更新】
--------------------------------------------------------------------------------
現在感覺,任務是先放在隊列裡,從隊列裡拿出來同步或者非同步執行,當然是不是這樣也有待考證。
如果是這樣的話,串列隊列只能一個一個拿出任務不管你是否阻塞原線程或者有沒有開闢新線程,任務都是一個一個執行。
並行隊列的話,如果是阻塞原線程的同步執行那也只能一個一個執行,如果是不阻塞原線程再開闢線程的話就可以一起執行了。
疑點在於
1、任務是不是先從隊列裡拿出並按隊列的規則執行,尤其是串列非同步(會開闢新的線程嗎?)和並行同步方面需要注意,他們之間的通訊是怎麼實現的?
答:在GDC中一個操作是多線程執行還是單線程執行取決於當前隊列類型和執行方法,只有隊列類型為並行隊列並且使用非同步方法呼叫執行時才能在多個線程中執行。
2、雖然說同步非同步區別在於是否阻塞原線程,但是除了開闢新的線程以外還有方法避免阻塞嗎?那同步非同步區別是不是就是有沒有開闢線程了?