参考:http://ios.jobbole.com/82622/
并发队列只能决定“是否”可以同时调度多个任务,不会决定开不开线程,并发队列的并发功能只有内部的任务是异步任务时,才有效。
同步的方式执行任务:在当前线程中依次执行任务。dispatch_sync()
异步的方式执行任务:新开线程在新线程中执行任务。dispatch_async()
GCD死锁原理
1.串行队列与并发队列:在使用GCD的时候,我们把需要处理的任务放到block中,然后将任务追加到相应的队列里面。这个队列叫做Dispatch Queue。存在两种Dispatch Queue一种是要等待上一个执行完,在执行下一个的Serial Dispatch Queue,这种叫做串行队列。另一种则是不需要上一个执行完,就能执行下一个的Concurrent Dispatch Queue,叫做并发队列。这两种,均遵循FIFO原则。
2.并发与并行的区别:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程。它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其他线程处于挂起状态,这种方式我们称之为并发。 当系统有一个以上CPU时,则线程的操作有可能非并发,当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行。
3.同步与异步:串行与并发针对的是队列,而同步与异步针对的是线程。最大的区别在于,同步线程要阻塞当前线程,必须要等待同步线程中的任务执行完,返回以后,才能继续下一个任务;而异步线程则是不用等待。
4.系统提供的两个队列:全局队列,也是一个并发队列 dispatch_get_global_queue。 主队列,在主线程中运行,因为主线程只有一个,所以这是一个串行队列 dispatch_get_main_queue。
5.自己创建的队列:
dispatch_queue_t serialQueue = dispatch_queue_create("com.dlg.serial",DISPATCH_QUEUE_SERIAL);//串行队列
dispatch_queue_t concurrentQueue =dispatch_queue_create("com.dlg.concurrent",DISPATCH_QUEUE_CONCURRENT);//并发队列
6.同步与异步线程的创建: dispatch_sync(...,^(block)) 同步线程。dispatch_async(..., ^(block)) 异步线程。
注意:一个任务可以是一个函数(function)或者是一个block!!!!
7.案例分析一(死锁):
NSLog(@"1");//任务一
dispatch_sync(dispatch_get_main_queue(), ^{ //同步线程(也是一个任务 可记做任务四)
NSLog(@"2");//任务二
});
NSLog(@"3");//任务三
控制台输出: 1
首先在主队列中(串行队列)任务一 nslog方法 、任务四 dispatch_sync方法、任务三 nslog方法 依次加入到主队列中 。当执行任务一的时候输出 1,当执行到任务四的时候 系统把任务四中的任务二(block块)放到主队列的队尾即任务三的后边。 要执行完任务四就必须等待block执行完后才能返回执行任务三。 最终的情况是,因为主队列在主线程中运行,主线程卡在了任务四上,要想执行完任务四,就必须执行完任务二(block)但是任务二在任务三的后面,需要等任务三执行完成才能执行到任务二。从而就产生了死锁。
注意:下边函数的行为就是把任务二加入到主队列中。
dispatch_sync(dispatch_get_main_queue(), ^{ //同步线程(也是一个任务 可记做任务四)
NSLog(@"2");//任务二
});
8.案例分析二:
NSLog(@"1"); // 任务1
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"2"); // 任务2
});
NSLog(@"3"); // 任务3
控制台输出: 1 2 3
请大家先思考下为什么输出顺序是1 2 3 ???
首先在主队列中(串行队列)任务一 nslog方法 、任务四 dispatch_sync方法、任务三 nslog方法 依次加入到主队列中 。当执行任务一的时候输出 1,当执行到任务四的时候系统把任务四中的任务二(block块)加入到全局队列(属于并发队列)中,并且阻塞,等待任务二执行完成并返回。当打印 2后,任务四执行完成,然后在执行任务三。
9.案例分析三:
dispatch_queue_t queue = dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1"); // 任务1
dispatch_async(queue, ^{
NSLog(@"2"); // 任务2
dispatch_sync(queue, ^{
NSLog(@"3"); // 任务3
});
NSLog(@"4"); // 任务4
});
NSLog(@"5"); // 任务5
//输出: 1 5 2