天天看點

iOS 多線程 同步和異步 串行和并行

    iOS中我們常使用dispatch_queue和NSOperationQueue來實作多線程。而串行和并行、同步和異步,這四個詞同時出現的地方是dispatch_queue。NSOperationQueue貼心的隐藏了這些東西,已經不需要我們來操心了。是以下面會使用dispatch_queue來展開。

    線程,線程是程式執行流的最小單元。

    串行隊列,後一個任務等待前一任務結束後再執行,按添加順序一個一個執行。

    并行隊列,後一個任務不會等待前一個任務,不等前一個任務完成就會配置設定新任務。

    串行和并行,這裡對應的是隊列的概念。隊列負責管理多個任務,隊列擁有一個線程池,池子裡有一個或者多個線程,它按要求将每個任務排程到某一個線程執行。

    抛開同步異步,首先來建立一個隊列 dispatch_queue_t ,DISPATCH_QUEUE_SERIAL、DISPATCH_QUEUE_CONCURRENT分别對應串行和并行

dispatch_queue_t serialQueue = dispatch_queue_create("my.serialQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
           

    然後再來說一下dispatch_sync和dispatch_async。同步和異步在這裡是線程概念,同步不會建立新的線程,會阻塞目前的線程在這個線程裡執行任務。而異步則不會阻塞目前線程,會選擇在恰當的時機在目前線程或者另開線程執行任務(看系統如何排程),開始任務和完成任務時間是不确定的。

iOS 多線程 同步和異步 串行和并行

在ViewDidLoad裡加添加代碼run

iOS 多線程 同步和異步 串行和并行

首先看到viewDidLoad是mainQueue來排程來的任務,而mainQueue是串行的(serial)。

這裡不能使用dispatch_sync(main,^{});串行隊列同步任務中(向同一個串行隊列添加同步任務),進行中的任務等待添加任務完成,添加的任務等待上一個任務完成,因為互相等待死循環。在currentQueue中謹慎使用dispatch_sync;

iOS 多線程 同步和異步 串行和并行
iOS 多線程 同步和異步 串行和并行
2018-07-06 17:04:19.093719+0800 test[23549:749696] 1
2018-07-06 17:04:44.473137+0800 test[23549:749696] 1sync <NSThread: 0x60c000073400>{number = 1, name = main}
2018-07-06 17:04:44.473316+0800 test[23549:749696] 2
2018-07-06 17:04:44.473441+0800 test[23549:749696] 3
2018-07-06 17:05:11.883097+0800 test[23549:749696] 3sync <NSThread: 0x60c000073400>{number = 1, name = main}
2018-07-06 17:05:14.271792+0800 test[23549:749696] 4
           

因為是同步,任務都被配置設定到了主線程,同步任務會阻塞目前線程,是以順序一定是1234。

再把serialQueue換成concurrentQueue,依然用sync同步,得到的結果是1234。同步隻會在目前線程(隻有一個線程)同時阻塞線程,并行隊列失去意義,結果和串行隊列一樣都是一個一個順序執行。  

上述代碼,我們将sync換成async異步,依然是serialQueue串行隊列。得到結果2413、2143、1234。串行隊列,一個一個執行,那麼1肯定在3前面。而異步操作不會阻塞線程,1、3和2、4之間的位置是不确定的;另外補充,串行異步情況下,串行一個一個執行,那麼異步一次配置設定一個線程就足夠了(隊列可以把任務送出到不同的線程,但串行同時存在的隻有一個任務也就是一個線程)。

上述代碼,換成異步并行

iOS 多線程 同步和異步 串行和并行
iOS 多線程 同步和異步 串行和并行
iOS 多線程 同步和異步 串行和并行

可見因為異步,1、3分别被配置設定到了線程thread 5、4中執行,(具體配置設定到哪個線程是不确定的)。

得到結果可能是13,也可能是31,因為是并行隊列,不會等待上一個任務完成,異步的執行又是不确定時間的,是以1和3的順序是不确定的。