GCD死锁案例解析

参考:http://ios.jobbole.com/82622/

案例一

NSLog(@"1"); // 任务1
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"2"); // 任务2
});
NSLog(@"3"); // 任务3

//打印结果:
1

分析:dispatch_sync 执行后,会同步任务(即先阻塞当前线程,优先在任务1所在线程执行当前的任务,而把任务2插入到main_queue尾部),所以任务2执行完了才会执行任务3。而任务2是针对main_queue的,只有等main_queue都执行完了才会执行任务2,而main_queue是串行队列,所以只有任务3完成后才会执行任务2。双方同时进入等待状态,造成死锁。

案例二

NSLog(@"1"); // 任务1
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    NSLog(@"2"); // 任务2
});
NSLog(@"3"); // 任务3

//打印结果:
1
2
3

分析:任务2在会在主线程优先执行任务2,故任务2执行完了才会执行任务3。同时任务2是插入到global队列尾部。所以理所当然的,先执行了2,再执行3。

案例三

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
// 5和2的顺序不一定

分析:这个案例没有使用系统提供的串行或并行队列,而是自己通过dispatch_queue_create函数创建了一个DISPATCH_QUEUE_SERIAL的串行队列。
执行任务1;

  • 遇到异步线程,将【任务2、同步线程、任务4】加入串行队列中。因为是异步线程,所以在主线程中的任务5不必等待异步线程中的所有任务完成;
  • 因为任务5不必等待,所以2和5的输出顺序不能确定;
  • 任务2执行完以后,遇到同步线程,这时,将任务3加入串行队列;
  • 又因为任务4比任务3早加入串行队列,所以,任务3要等待任务4完成以后,才能执行。但是任务3所在的同步线程会阻塞,所以任务4必须等任务3执行完以后再执行。这就又陷入了无限的等待中,造成死锁。

案例四

NSLog(@"1"); // 任务1
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"2"); // 任务2
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"3"); // 任务3
    });
    NSLog(@"4"); // 任务4
});
NSLog(@"5"); // 任务5
//打印结果:
1
2
5
3
4
// 5和2的顺序不一定

分析:
1.执行任务1。
2.多线程执行任务2,主线程执行任务5,前后可能随机。
3.任务3执行的时候,因为是同步,所以会先阻塞global线程,然后把任务3插入到主线程后面,等待主线程执行完了,再执行任务3。
4.任务3执行完,任务4所在的global线程阻塞结束,所以最后执行任务4。

如果在任务5前面加一个,sleep(3); 那么结果依然是这个。任务3会一直等待任务5,任务4也会一直等待任务3。

案例五

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"1"); // 任务1
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2"); // 任务2
    });
    NSLog(@"3"); // 任务3
});
NSLog(@"4"); // 任务4
while (1) {
}
NSLog(@"5"); // 任务5
打印结果:
1
4
// 1、4顺序不一定

分析略,见案例四分析。

你可能感兴趣的:(GCD死锁案例解析)