你的位置:首页 > 操作系统

[操作系统]关于GCD的探知及个人见解(希望牛人们不吝赐教,以解我惑!)


对于GCD中的同步任务、异步任务的区别,之前有前辈们有这么认为的:

  1. 同步任务:不会开辟线程;
  2. 异步任务:会开辟新的线程,开辟线程的个数,视资源需求。

后来部分人更新了微博简书称:同步任务、异步任务的区别在于前者会阻塞主线程,活着不回阻塞主线程。一开始我也这么认为,但是后来我写Demo的时候我就糊涂,不知道是我理解错了,还是怎么滴,就是解释不通。下面是练习代码:

- (void)testOne {    NSLog(@"testOne_start - %@",[NSThread currentThread]);    dispatch_queue_t queue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);    dispatch_sync(queue, ^{        NSLog(@"testOne_sync - %@",[NSThread currentThread]);  });    NSLog(@"testOne_end - %@",[NSThread currentThread]);}

运行结果如下:

 2016-01-15 15:18:09.024 GCD练习[4033:28550] testOne_start - <NSThread: 0x7fafe8506790>{number = 1, name = main}
 2016-01-15 15:18:09.025 GCD练习[4033:28550] testOne_sync - <NSThread: 0x7fafe8506790>{number = 1, name = main}
 2016-01-15 15:18:09.025 GCD练习[4033:28550] testOne_end - <NSThread: 0x7fafe8506790>{number = 1, name = main}

 

 

- (void)testTwo {    NSLog(@"testTwo_start - %@",[NSThread currentThread]);    dispatch_queue_t queue = dispatch_get_main_queue();    dispatch_sync(queue, ^{        NSLog(@"testTwo_sync - %@",[NSThread currentThread]);  });    NSLog(@"testTwo_end - %@",[NSThread currentThread]);}

运行结果如下:testTwo_start - <NSThread: 0x7fc711f046e0>{number = 1, name = main

两段代码很简单,唯一的区别就是前者是把block添加到一个我们新创建的串行队列中去了,而后者是把block添加到主队列中去了,而主队列本身也是一个串行队列。

按照前人所说,同步任务会阻塞主线程,后者还能解释的清楚,但是前者我是看了很久都无法解释。都是主线程被阻塞了,为什么从自己创建的串行队列中出列的block任务就能执行,而添加到主队列中的block任务就不能执行呢? 不明白,那就去查资料呗!这是我查到的一个关于串行队列的解释:serial dispatch queue一次只能执行一个任务, 当前任务完成才开始出列并启动下一个任务。 “当前任务完成才开始出列并启动下一个任务” 。 所以我在想 是不是同步任务不能立即返回(必须等待block执行完毕),导致下一个任务无法出列执行。简单的说就是 同步任务是阻塞了队列,而非阻塞了线程(把同步任务添加到主队列中,会导致同步任务后面的队列无法出列执行,跟线程阻塞状态一样)。以下是我对上面两份代码前者不会导致死锁以及后者会导致死锁的个人理解:

  • 串行队列里任务是一个一个执行的,只有当前任务完成才会出列下一任务
    在这里我们创建了一个串行队列,以及一个同步任务,并将这个同步任务(官方文档:像队列提交一个block,并且这个函数不会返回,直到block完成),扔进了这个串行队列中去了。                                   程序执行:
    1.主队列 出列第一个NSLog;

    2.继而执行同步任务,同步任务创建了一个任务,并扔进了serial串行队列中;因为同步任务必须执行完block才返回,故此时主队列认为 同步任务 尚未完成,因此第三个 NSLog任务无法出列,继续执行block(从serial出列) ,执行完block同步任务返回。

    3.第三个NSLog任务出列。

 

  • 1.主队列出列 第一个NSLog任务执行完毕。

    2.主队列出列 第二个任务 同步任务, 同步任务创建一个block任务 并添加到主队列中,以等待出列 执行block,但同步任务 必须等待block执行完毕才能返回,但是对于串行队列(主队列)来说只有上一个任务完成了,下一个任务才能出列,所以block任务无法出列 执行,同步任务又等带block出列执行,死锁。

     上面便是我的理解,也是我自己能对上面两份代码作出的唯一解释,但毕竟跟前人说的相反(在查阅资料的时候也发现有人认为是阻塞队列,不过被人反驳了),还是希望大神为我指点,以解我心中之疑惑。