GCD入门介绍三----线程死锁

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] ------阻塞主线程









你可能感兴趣的:(多线程,阻塞,gcd)