基本知识点:
死锁:
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
队列:
- 串行队列:任务一个一个按顺序执行,后面的任务必须等待前面的任务执行完毕后才能执行。
- 并发队列:多个任务可以同时执行, 后面的任务不需等待前面的任务执行完毕就可以执行。
同步(sync) 和 异步(async):
- 同步: 立即执行(需要等待),不具备开启新线程的能力
- 异步: 不需等待。具备开启新线程的能力,但是不一定会开启。(如:队列为主队列时)
主队列
主队列是一个特殊的串行队列,主队列的任务在主线程中执行。
死锁分析
场景一
- (void)viewDidLoad {
[super viewDidLoad];
[self test1];
}
- (void)test1 {
NSLog(@"任务1------");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"任务2------");
});
NSLog(@"任务3--------");
}
上面代码会发生死锁, 原因:queue为主队列,任务2又是同步执行。 任务2的执行必须等待 viewDidLoad 这个任务执行完, 而viewDidLoad这个任务执行完的前提是任务2执行完,两者相互等待,造成死锁。解决方案:(1)将同步改为异步 (2)将任务2加入到其他队列中
场景二
- (void)test2 {
NSLog(@"任务1------");
// 创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("com.longchi", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{ // 异步任务
NSLog(@"任务2------");
dispatch_sync(queue, ^{
NSLog(@"任务3------");
});
NSLog(@"任务4--------");
});
NSLog(@"任务5--------");
}
上面代码也会发生死锁, 原因:queue为串行队列,任务3的执行必须等待异步任务的执行完毕,而异步任务要执行完毕就必须等待任务3先执行完。两者相互等待,造成死锁。 解决方案:(1) queue改为并发队列 (2) 将任务3加入其他队列 (3) 任务3也异步执行。
总结
使用sync
函数往当前串行队列
中添加任务,会卡住当前的串行队列(会发生死锁
)。