1、在主线程执行以下代码打印结果是什么?
- (void)test {
NSLog(@"1");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"2");
});
NSLog(@"3");
}
打印结果:
~: 1
并报错: !Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
分析原因:
test方法是在主线程里执行的任务(任务1),已经进入主队列当中。
在test方法内部追加了一个同步执行的任务(任务2),dispatch_sync的特点是要在当前线程马上执行,执行完毕后才会继续往下执行。
由于主队列是串行队列,需要依次执行任务,所以任务2要等待任务1执行结束才能执行。
而又因为任务1要等待任务2执行结束才算执行结束。
这样就造成了相互等待的情况,也就是线程死锁,导致代码无法继续执行。
2、在主线程执行以下代码打印结果是什么?
- (void)test {
NSLog(@"1");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"2");
});
NSLog(@"3");
}
打印结果:
~: 1
~: 3
~: 2
和上面代码唯一的区别就是换成了dispatch_async执行,dispatch_async的特点是不要求马上执行,会等上一个任务执行完成再执行。所以不会造成死锁。
3、在主线程执行以下代码打印结果是什么?
- (void)test {
NSLog(@"1");
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"2");
dispatch_sync(queue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
打印结果:
~: 1
~: 5
~: 2
分析原因:
test是在主线程里执行的任务。
创建新的queue是串行队列,又使用async执行任务(任务1),所以会开启新的线程,在新线程里执行。
在任务1中添加了一个sync任务(任务2),由于queue是串行,所以又造成了和问题一同样的情况。
任务2要求马上执行,而任务2又要等待任务1执行完毕才会执行,任务1又要等待任务2执行结束才算完成,这样相互等待造成死锁。
4、在主线程执行以下代码打印结果是什么?
- (void)test {
NSLog(@"1");
// 创建并发队列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"2");
dispatch_sync(queue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
打印结果:
~: 1
~: 5
~: 2
~: 3
~: 4
分析原因:
和上一个问题的差别就是任务1和任务2是在并发队列里执行,并发队列的特点就是可以同时执行多个任务。
所以即使任务2需要马上执行,但是任务1也会同步执行,所以不会造成死锁。
5、总结
使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列(产生死锁)