GCD确实给iOS开发者提供了很多便利,它的功能也很强大。但相比NSOperation无法提供取消任务以及添加依赖的功能。但GCD如果用的不好或者用的地方不对就会出现线程死锁的情况。我将通过几个例子进行说明:
例子1:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"--------1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"-------2");
});
NSLog(@"-------3");
}
GCD Queue分为三种:
1.main queue:主队列,主线程就是在这个队列中。
2.Global queues:全局并发队列。
3.用户队列:使用函数dispatch_queue_create创建的自定义队列
dispatch_sync和dispatch_async区别
dispatch_sync 同步队列,dispatch_sync函数不会立即返回,会阻塞当前线程,等待block同步执行完成。
dispatch_async 异步队列,dispatch_async函数会立即返回,block会在后台异步执行。
分析上面代码:
输出结果
2015-12-11 11:28:40.502 test003[4276:148470] --------1
viewDidLoad在主线程(dispatch_get_main_queue())中,执行到sync时向dispatch_get_main_queue()插入同步线程。sync会等到后面block执行完成才返回。sync又在dispatch_get_main_queue()队列中,它是串行队列,sync是后加入的,前一个队列是主线程,sync想执行block必须等待主线程执行完成。主线程等待sync返回,去执行后续内容。sync等待mainThread执行完成,mainThread等待sync函数返回,照成死锁。
例子2:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSLog(@"-------1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"-------2");
});
});
NSLog(@"-------3");
}
输出结果:
2015-12-11 13:55:14.166 test003[5174:194372] --------1
2015-12-11 13:55:14.168 test003[5174:194372] -------3
2015-12-11 13:55:14.195 test003[5174:194372] -------2
程序执行完成,不会出现死锁。
async在主线程中创建了一个异步线程加入全局并发队列,async不会等待block执行完成,就立即返回。
1.async会立即返回,viewDidLoad执行完毕,主线程也执行完毕。
2.全局并发队列立即执行异步block,打印1,当执行到sync时它会等待block执行完成才返回,即等待dispatch_get_main_queue()队列中的mainThread执行完成,然后才开始调用block。
因为1和2几乎同时执行,2在全局并发队列上,2中执行到sync时1可能已经执行完成或等了一会mainThread很快退出,2执行后续内容。
如果阻塞了主线程,2中的sync就无法执行啦,mainThread永远不会退出,sync就永远等待着
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSLog(@"-------1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"-------2");
});
NSLog(@"-------3");
});
NSLog(@"------阻塞主线程");
while (1) {
}
NSLog(@"-----2---阻塞主线程");
}
打印如下:
2015-12-11 14:16:41.566 test003[5403:204633] -------1
2015-12-11 14:16:41.566 test003[5403:204585] ------阻塞主线程