多線程單線程,同步異步,併發並行,串行隊列並行隊列,看這裏就對了

多線程開發用了好久,可是一直沒去深刻了解。長久以來一直有一些迷惑。直到深刻了解後,才發現了之前的理解有很多錯誤的地方。html

單線程等於同步,多線程等於異步node

  • 這種理解很直觀,畢竟只有一個線程怎麼異步?

Node.js表示不服,我就是單線程,我也能異步。談一談Node中的異步和單線程
看完這篇文章我明白了單線程也能異步,把IO等耗時的操做比做燒水,我能夠在這個時候切菜,這就是異步啊。
等等,彷佛有點不對,那io又誰來開啓,又誰來通知cpu我已經結束了呢?
Node.js異步IO的實現,這篇文章解決了個人疑惑。ios

  • Node.js裏面只有本身寫的代碼是跑在主線程上,可是內部並非單線程的,由C編寫的底層開啓了線程作IO操做。

恍然大悟,我如今的理解就是,會有一個可運行的線程池在等待cpu的使用權。相似IO,網絡請求這種耗時乾等的操做,線程會放到須要等待的線程池中(阻塞),不會獲取cpu的使用權,直到操做完成git

這個理解了,併發和並行就很容易了。github

  • 每一個線程得到cpu的使用權的時間就是一個時間片,用完了就必需要等下次了。時間片很是短,人根本意識不到,感受就是並行的,但其實只是"僞並行",也就是併發。

概念都講結束了,如今能夠談談iOS的多線程了。其實理論都同樣,無非線程的得到,開啓,結束等。可是iOS有個不一樣,他有GCD,那真是神器。
關於GCD的串行隊列,並行隊列,一直以來都有一個錯誤的理解:網絡

隊列就是線程,async就是另開線程,sync就是阻塞線程多線程

實踐才能出真知,要想真明白,async,sync,串行隊列,並行隊列,主隊列,仍是要親自測一下才行。併發

  • 主線程下,是否開啓新線程
//主隊列
dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"%@",[NSThread currentThread]);
});
    
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"%@",[NSThread currentThread]);
});

//串行隊列
dispatch_queue_t ser_queue = dispatch_queue_create("串行", DISPATCH_QUEUE_SERIAL);
    
dispatch_async(ser_queue, ^{
    NSLog(@"1-%@",[NSThread currentThread]);
});

dispatch_async(ser_queue, ^{
    NSLog(@"2-%@",[NSThread currentThread]);
});
    
dispatch_sync(ser_queue, ^{
    NSLog(@"3-%@",[NSThread currentThread]);
});

//並行隊列
dispatch_queue_t con_queue = dispatch_queue_create("並行", DISPATCH_QUEUE_CONCURRENT);
    
dispatch_async(con_queue, ^{
    NSLog(@"1-%@",[NSThread currentThread]);
});

dispatch_async(con_queue, ^{
    NSLog(@"2-%@",[NSThread currentThread]);
});
    
dispatch_sync(con_queue, ^{
    NSLog(@"3-%@",[NSThread currentThread]);
});
  • 非主線程下,異步是否新開線程
dispatch_queue_t ser_queue = dispatch_queue_create("串行", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t con_queue = dispatch_queue_create("並行", DISPATCH_QUEUE_CONCURRENT);

    
    dispatch_async(ser_queue, ^{
        NSLog(@"1-%@",[NSThread currentThread]);
        dispatch_async(ser_queue, ^{
            NSLog(@"1-%@",[NSThread currentThread]);
        });
    });
    
    dispatch_async(ser_queue, ^{
        NSLog(@"2-%@",[NSThread currentThread]);
        dispatch_async(con_queue, ^{
            NSLog(@"2-%@",[NSThread currentThread]);
        });
    });
    
    dispatch_async(con_queue, ^{
        NSLog(@"3-%@",[NSThread currentThread]);
        dispatch_async(con_queue, ^{
            NSLog(@"3-%@",[NSThread currentThread]);
        });
    });
    
    dispatch_async(con_queue, ^{
        NSLog(@"4-%@",[NSThread currentThread]);
        dispatch_async(ser_queue, ^{
            NSLog(@"4-%@",[NSThread currentThread]);
        });
    });

    dispatch_async(ser_queue, ^{
        NSLog(@"5-%@",[NSThread currentThread]);
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"5-%@",[NSThread currentThread]);
        });
    });

    dispatch_async(con_queue, ^{
        NSLog(@"6-%@",[NSThread currentThread]);
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"6-%@",[NSThread currentThread]);
        });
    });
  • 非主線程下,同步是否新開線程
dispatch_async(ser_queue, ^{
        NSLog(@"1-%@",[NSThread currentThread]);
        dispatch_sync(ser_queue, ^{
            NSLog(@"1-%@",[NSThread currentThread]);
        });
    });
    
    dispatch_async(ser_queue, ^{
        NSLog(@"2-%@",[NSThread currentThread]);
        dispatch_sync(con_queue, ^{
            NSLog(@"2-%@",[NSThread currentThread]);
        });
    });

    dispatch_async(con_queue, ^{
        NSLog(@"3-%@",[NSThread currentThread]);
        dispatch_sync(con_queue, ^{
            NSLog(@"3-%@",[NSThread currentThread]);
        });
    });

    dispatch_async(con_queue, ^{
        NSLog(@"4-%@",[NSThread currentThread]);
        dispatch_sync(ser_queue, ^{
            NSLog(@"4-%@",[NSThread currentThread]);
        });
    });

    dispatch_async(ser_queue, ^{
        NSLog(@"5-%@",[NSThread currentThread]);
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"5-%@",[NSThread currentThread]);
        });
    });
    
    dispatch_async(con_queue, ^{
        NSLog(@"6-%@",[NSThread currentThread]);
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"6-%@",[NSThread currentThread]);
        });
    });

結論:
結果就不貼出來了,仍是本身親自測下比較好。看看本身的想法和答案是否一致但是一件很快樂的事情。
基本上覆蓋了全部可能。感受更像是面向隊列來的,線程的調度是系統本身分配的。異步

測下來感受就是回答了兩個問題:async

  • async何時會新開線程
  • sync何時會致使死鎖

個人答案:

  • 主隊列:必定會在主線程
  • 串行隊列:async會開一條線程
  • 並行隊列:async會開多條線程
  • 死鎖:必須是串行隊列,其次提交block所在隊列和把block放進去的隊列是同一個。
  • async不一樣的隊列,基本上是在不一樣的線程上。(存疑)
  • 提交block的隊列和block放進去的隊列是同一個,無論串行並行,都在同一個線程上。(存疑)

GCD是神器,還有好多須要學習的地方,推薦幾篇經典的文章:
GCD掃盲篇巧談GCD
GCD進階篇
死鎖,圖文並茂,清晰易懂

相關文章
相關標籤/搜索