多线程单线程,同步异步,并发并行,串行队列并行队列,看这里就对了

多线程开发用了好久,可是一直没去深刻了解。长久以来一直有一些迷惑。直到深刻了解后,才发现了之前的理解有很多错误的地方。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进阶篇
死锁,图文并茂,清晰易懂

相关文章
相关标签/搜索