GCD死锁原因
GCD死锁的原因是队列阻塞,而不是线程阻塞!
串行和并行
串行和并行都是相对于队列而言的
-队列(负责调度任务)
-串行队列:一个接一个的调度任务
-并发队列:可以同时调度多个任务
在使用GCD的时候,我们会把需要处理的任务放到Block中,然后将任务追加到相应的队列里面,这个队列,叫做Dispatch Queue
。
队列一般存在于两种Dispatch Queue,
一种是要等待上一个执行完,再执行下一个的Serial Dispatch Queue
,这叫做串行队列;
另一种,则是不需要上一个执行完,就能执行下一个的Concurrent Dispatch Queue
,叫做并行队列。
这两种,均遵循FIFO原则,也就是先进先出原则。
同步与异步
串行与并行针对的是队列,而同步与异步,针对的则是线程
最大的区别在于,同步线程要阻塞当前线程,必须要等待同步线程中的任务执行完,返回以后,才能继续执行下一任务;而异步线程则是不用等待。
GCD API
1.系统标准提供的两个队列
// 全局队列,一个特殊的并行队列
dispatch_get_global_queue
// 主队列,在主线程中运行,因为主线程只有一个,所以这是一个特殊的串行队列
dispatch_get_main_queue
2.除此之外,还可以自己生成队列
// 从DISPATCH_QUEUE_SERIAL看出,这是串行队列
dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL)
// 同理,这是一个并行队列
dispatch_queue_create("com.demo.concurrentQueue", DISPATCH_QUEUE_CONCURRENT)
3.同步与异步线程的创建:
dispatch_sync(..., ^(block)) // 同步线程
dispatch_async(..., ^(block)) // 异步线程
案例
1.会产生死锁
NSLog(@"1"); // 任务1
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"2"); // 任务2
});
NSLog(@"3"); // 任务3
2.不会产生死锁
dispatch_queue_t queue = dispatch_queue_create("ent.nensl.sda", DISPATCH_QUEUE_SERIAL);
NSLog(@"111111");
dispatch_sync(queue, ^{
NSLog(@"222222————%@",[NSThread currentThread]);
});
NSLog(@"333333");
ent.nensl.sda这个队列的执行线程是主线程,同步方式不会开辟新线程,但这是我们是将任务添加到了ent.nensl.sda这个队列中,所以主线程会来立即执行这个队列中的任务,执行完成后就会返回,主线程不会继续被阻塞。所以不会死锁。