初探GCD

来源:互联网 发布:八爪鱼采集器的源码 编辑:程序博客网 时间:2024/06/04 18:05

GCD的编程核心是dispatch队列,block是被放到队列中去执行的。你既可以使用系统提供的队列,也可以自己创建队列。队列有串行和并行之分,block可被同步执行或异步执行。这篇博客就简单介绍下串并行,同步异步状态下的block执行结果区别。

大家很容易把同步异步和阻塞非阻塞的概念混淆。同步和异步关注的是消息的通信机制,阻塞和非阻塞关注的是程序在等待(调用)结果时的状态。(这4个概念的详细介绍可以参考点击打开链接)

  1. 同步:发出调用之后,在没有得到计算结果前就不返回,直到有返回结果为止。(必须等到被调用的函数有了返回值或计算完毕之后,才能够继续执行下面的代码)
  2. 异步:发出调用之后立即返回,没有得到结果。最后是通过回调函数等来得到结果的。(无需等到被调用函数计算完毕,就可以立即执行后续代码)

串行跟并行就不再啰嗦了,这里只要记住一点即可:加入到串行队列中的block是按照FIFO顺序执行。下面进入正题,串行并行,同步异步相组合block的结果有何不同。

注意:下面代码的执行结果打印时间

  • 将block放到串行队列中

<span style="font-size:14px;">dispatch_queue_t queue = dispatch_queue_create("xiao.custom.serial.syn.queue", DISPATCH_QUEUE_SERIAL);    dispatch_sync(queue, ^{        NSLog(@"serial 1 start");        [NSThread sleepForTimeInterval:2];        NSLog(@"serial 1 end");    });        NSLog(@"上面是同步执行,block完毕之后,我才能够得到执行");        dispatch_sync(queue, ^{        [NSThread sleepForTimeInterval:4];        NSLog(@"serial 2 end");    });            dispatch_async(queue, ^{        NSLog(@"serial 3 start");        [NSThread sleepForTimeInterval:3];        NSLog(@"serial 3 end");    });        NSLog(@"即使3异步执行也要等到1,2结束才开始,因为3被放到了串行队列,FIFO");    NSLog(@"但是3的执行时间不会影响它下面的代码,你看3睡秒了3秒不是没有影响到我的执行吗");</span><span style="font-size:12px;"></span>

<span style="font-size:14px;">2015-12-04 19:25:41.635 Learn_GCD[3173:1585477] serial 1 start2015-12-04 19:25:43.636 Learn_GCD[3173:1585477] serial 1 end2015-12-04 19:25:43.636 Learn_GCD[3173:1585477] 上面是同步执行,block完毕之后,我才能够得到执行2015-12-04 19:25:47.638 Learn_GCD[3173:1585477] serial 2 end2015-12-04 19:25:47.638 Learn_GCD[3173:1585477] 即使3异步执行也要等到1,2结束才开始,因为3被放到了串行队列,FIFO2015-12-04 19:25:47.638 Learn_GCD[3173:1585631] serial 3 start2015-12-04 19:25:47.638 Learn_GCD[3173:1585477] 但是3的执行时间不会影响它下面的代码,你看3睡秒了3秒不是没有影响到我的执行吗2015-12-04 19:25:50.639 Learn_GCD[3173:1585631] serial 3 end</span>

  • 将block放到并行队列中
<span style="font-size:14px;">dispatch_queue_t queue = dispatch_queue_create("xiao.custom.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);    dispatch_async(queue, ^{        NSLog(@"concurrent 1 start");        [NSThread sleepForTimeInterval:2];        NSLog(@"concurrent 1 end");    });        dispatch_async(queue, ^{        [NSThread sleepForTimeInterval:4];        NSLog(@"concurrent 2 end");    });        dispatch_async(queue, ^{        NSLog(@"concurrent 3 start");        [NSThread sleepForTimeInterval:3];        NSLog(@"concurrent 3 end");    });</span><span style="font-size:18px;"></span>


生成一个并发执行队列,block被分发到多个线程去执行 1,2,3的睡秒时间互不影响   18:57:40.813 Learn_GCD[2931:1500822] 1 start  18:57:40.813 Learn_GCD[2931:1500824] 3 start  18:57:42.814 Learn_GCD[2931:1500822] 1 end  18:57:43.814 Learn_GCD[2931:1500824] 3 end  18:57:44.813 Learn_GCD[2931:1500823] 2 end


如果我们将block放到并行队列中同步执行会是什么结果呢?

<span style="font-size:14px;">dispatch_queue_t queue = dispatch_queue_create("xiao.custom.concurrent.queue2", DISPATCH_QUEUE_CONCURRENT);    dispatch_sync(queue, ^{        NSLog(@"concurrent 1 start");        [NSThread sleepForTimeInterval:2];        NSLog(@"concurrent 1 end");    });        dispatch_sync(queue, ^{        [NSThread sleepForTimeInterval:4];        NSLog(@"concurrent 2 end");    });        dispatch_sync(queue, ^{        NSLog(@"concurrent 3 start");        [NSThread sleepForTimeInterval:3];        NSLog(@"concurrent 3 end");    });</span><span style="font-size:18px;"></span>

<span style="font-size:14px;">生成一个并发执行队列,block被分发到多个线程去执行     因为是同步执行,所以即使被分发到多个线程,也要等到上一个block返回之后下一个才能执行          2015-12-04 19:31:21.546 Learn_GCD[3199:1599520] concurrent 1 start     2015-12-04 19:31:23.547 Learn_GCD[3199:1599520] concurrent 1 end     2015-12-04 19:31:27.548 Learn_GCD[3199:1599520] concurrent 2 end     2015-12-04 19:31:27.548 Learn_GCD[3199:1599520] concurrent 3 start     2015-12-04 19:31:30.549 Learn_GCD[3199:1599520] concurrent 3 end</span><span style="font-size:18px;"></span>



再来看看这段代码为什么会出现死锁

dispatch_queue_t queue = dispatch_queue_create("xiao.custom.serial.queue2", DISPATCH_QUEUE_SERIAL);        dispatch_sync(queue, ^{                dispatch_sync(queue, ^{                    });            });

block被放到串行队列中,同步执行。


先进入queue的block先执行,这个block里嵌套了一个block并且又是跟它在同一个queue里执行的。后进入queue的block要等到先进入的执行完毕它才能执行(FIFO),它就处在等待状态。而先进入的block也在等它的第一行代码执行完毕之后才能执行之后的代码。故而造成死锁。

0 0
原创粉丝点击