GCD的同异步、串并行以及队列死锁的问题

本文详细介绍了GCD中同步异步的区别以及并发串行的执行方式,并通过实例展示了全局并发队列、主队列和自定义队列在不同模式下的运行效果,特别强调了在主队列使用同步方式可能导致的死锁问题。
摘要由CSDN通过智能技术生成

概念解释:

同步和异步决定了要不要开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力

并发和串行决定了任务的执行方式
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务

通过GCD可获得的三种队列
1.全局并发队列
2.主队列(跟主线程相关联的队列)
3.自定义队列

三种队列通过同步、异步方式,实验下6种方式:

1.全局并发队列,同步方式

- (void)count{
    for (int i = 0; i < 5; i++) {
        NSLog(@"num:%d",i);
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //获取全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_sync(queue, ^{
        NSLog(@"下载图片1---%@",    [NSThread currentThread]);
        [self count];
    });
    dispatch_sync(queue, ^{
        NSLog(@"下载图片2---%@",    [NSThread currentThread]);
        [self count];
    });

}

运行结果:
这里写图片描述
number = 1表示当前是主线程,因为是dispatch_sync同步方式往全局队列中添加的任务,可见并没有开启新的线程。

2.全局并发队列,异步方式

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        NSLog(@"下载图片3---%@",    [NSThread currentThread]);
        [self count];
    });
    dispatch_async(queue, ^{
        NSLog(@"下载图片4---%@",    [NSThread currentThread]);
        [self count];
    });
}

运行结果:

这里写图片描述

可以看到number =4,number = 3,意味着开启了两个子线程去完成任务,观察num:0 num:0 ,交替打印出num的值,可以理解为两个任务同时进行,即并行处理

3.主队列,同步方式

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"下载图片1---%@",    [NSThread currentThread]);
        [self count];
    });
    dispatch_sync(queue, ^{
        NSLog(@"下载图片2---%@",    [NSThread currentThread]);
        [self count];
    });
}

这里运行,看起来并没有什么反应,也没有什么什么结果在Xcode上打印出来,为什么呢?这里涉及到串行队列中执行串行同步操作造成死锁的问题。

*首先大环境是主队列(主队列本质是串行队列 遵循FIFO),在主队列中,使用同步函数在主队列(相当于在相同的串行队列)末尾加入了任务。主队列 遇到了同步函数,准备继续往下执行程序,但是同步函数这时候也要执行,这意味着程序需要等待同步函数执行完成后才能继续。那么同步函数什么时候执行完成呢?同步函数需要等它自己block中的任务执行结束,而block种的任务什么时候执行结束呢?根据串行队列FIFO原则,要等待主队列中block这个任务前面所有的任务完成,而block任务是在主队列队尾,block前面的任务至少还有一个同步函数dispatch_sync()这个任务,所以block必须等待dispatch_sync()执行完。 那么问题来了,dispatch_sync()等待block执行完,block又在等待dispatch_sync()执行完,互相等待,这就造成死锁了。主要原因是主队列是串行队列。

4.主队列,异步方式

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [self count];
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"下载图片3---%@",    [NSThread currentThread]);
        [self count];
    });
    dispatch_async(queue, ^{
        NSLog(@"下载图片4---%@",    [NSThread currentThread]);
        [self count];
    });
}

这里写图片描述

分析一下:
*异步方式开启,等主线程执行完操作,才处理主队列中的任务
*虽然是异步方式,但是number = 1,并没有开启新的线程

5.自创建串行队列,同步方式

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"下载图片1---%@",    [NSThread currentThread]);
        [self count];
    });
    dispatch_sync(queue, ^{
        NSLog(@"下载图片2---%@",    [NSThread currentThread]);
        [self count];
    });
}


*同步方式,串行队列,没有开启新线程。
*由于同步函数不具备开启新线程的能力,所以就不列举同步函数执行并发队列的 例子了。

这里写图片描述

6.自创建并发队列,异步方式

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        NSLog(@"下载图片1---%@",    [NSThread currentThread]);
        [self count];
    });
    dispatch_sync(queue, ^{
        NSLog(@"下载图片2---%@",    [NSThread currentThread]);
        [self count];
    });
}

这里写图片描述

*异步方式,观察number =3,number=4,意味着,开启了两个新的线程处理任务
*num打印的值来看,由于创建的并发队列,所以并行处理。类似例子1中的全局队列,同步方式。

小结

方式全局队列主队列自创建队列
同步未开启新线程,串行执行任务未开启新线程,串行执行任务未开启新线程,串行执行任务
异步开启新线程,并发执行任务开启新线程,串行执行任务未开启新线程,串行执行任务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值