GCD同步异步队列笔记

2019-11-05  本文已影响0人  小如99

GCD的2个核心概念

GCD会自动将队列中的任务取出,放到对应的线程中执行;
任务的取出遵循对象的FIFO原则:先进先出,后进后出

程序员要做的,将任务添加到队列;队列按照程序员指定的方式,调度任务。执行任务的方法:同步/异步

同步:一个任务没有结束,就不会执行下一个任务

异步:不用等待任务执行完毕,就会执行下一个任务

主队列(dispatch_get_main_queue()):供主线程调度,是串行队列

全局队列(dispatch_get_global_queue(0, 0)):是并行队列

现在有以下几种组合:

串行异步  
串行同步
并行同步
并行异步

先看下四种情况是否开辟新线程,我写了代码执行得到如下log

serial async thread is <NSThread: 0x1006008f0>{number = 2, name = (null)}
serial sync thread is <NSThread: 0x10050d920>{number = 1, name = main}
concurrent sync thread is <NSThread: 0x10050d920>{number = 1, name = main}
concurrent async thread is <NSThread: 0x1006008f0>{number = 2, name = (null)}
global queue async thread is <NSThread: 0x1006008f0>{number = 2, name = (null)}
global queue sync thread is <NSThread: 0x10050d920>{number = 1, name = main}

可以看到

串行异步    开辟新线程
串行同步    不开辟新线程
并行同步    不开辟新线程
并行异步    开辟新线程

总结:线程的开辟跟队列是否是串行还是并行无关,异步开辟新线程,同步不开辟新线程

看log中没有主队列的log,因为主队列异步没执行,主队列同步会造成crash。

主队列同步执行为什么会Crash?

首先我们先看下串行队列同步是否有问题,代码如下:

NSLog(@"串行同步 start");
dispatch_queue_t serialSync = dispatch_queue_create("Judith_SerialSQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialSync, ^{
    NSLog(@"serial sync thread is %@",[NSThread currentThread]);
});
NSLog(@"串行同步 end");

得到的log如下:

串行同步 start
serial sync thread is <NSThread: 0x100605cf0>{number = 1, name = main}
串行同步 end

运行正常,所以串行队列同步是不会crash的,只是主队列同步会crash,那为什么主队列同步会导致crash呢?

我们看下主队列同步的代码:

+ (void)quenTest {
    //主队列同步  死锁
    NSLog(@"主队列同步 start");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"main queue sync thread is %@",[NSThread currentThread]);
    });
    NSLog(@"主队列同步 end");
}

主队列在执行dispatch_sync,函数会把一个block加入到指定的队列,此函数要求执行完block才返回,函数要求此时去执行block内容,但是主队列此时还卡在函数,函数线程还在,不能去执行block,也就是说函数和block是两个任务,在队列中前后关系,两个任务相互等待,导致死锁,产生crash。若是异步,函数添加完block就返回,顺序执行block内容,不存在死锁问题。

本文代码地址 GCDTest

上一篇 下一篇

猜你喜欢

热点阅读