GCD的一点总结

本文介绍了iOS开发中GCD的使用,包括异步和同步提交、并发队列与串行队列的组合、dispatch_barrier_async、dispatch_after、dispatch_once、dispatch_apply等API的使用场景和注意事项。还提到了GCD中的队列类型(主队列、全局队列和自定义队列)以及如何设置队列优先级。最后讨论了信号量dispatch_semaphore_t在同步操作中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       iOS开发中经常会用到多线程的技术,官方提供的多线程api包括pthread、NSThread、GCD和NSOperation;其中pthread是C的接口,对于开发者来说不够友好,NSThread是一个比较简单的api,使用场景有限,GCD是苹果官方提供的系统级的线程管理,api丰富,执行性能高,NSOperation是基于GCD的封装,本篇文章是工作中对于GCD使用的一些总结。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"do something");

        dispatch_async(dispatch_get_main_queue(), ^{

            NSLog(@"do some other thing");

        });

    });

      上述代码是GCD最简单的一种用法。子线程进行耗时操作,主线程刷新UI或者做动画,但是GCD的强大远不止这些。dispatch_async和dispatch_sync是block的提交方式,分别代表异步提交和同步提交,队列分为并发队列和串行队列,提交方式和队列的组合有四种场景,如下方表格所示:

  并发队列/concurrent 串行队列/serial
dispatch_async 并发执行 同步执行
dispatch_sync 同步执行效果 同步执行效果

  接下来看一下GCD提供的api:

        dispatch_async(dispatch_queue_t queue, dispatch_block_t block):异步提交block进队列的api,提交后会立即返回,不会等待block被执行完,执行队列决定提交进去的block是同步执行还是并发执行。

        dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block):同步提交block进队列的api,提交后不会立即返回,同时会阻塞当前线程,等到block执行完成。切记不可同步提交block进主队列,结果会造成死锁。

        dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block):通过该api提交的block,会在该队列完成之前提交的所有的block后才会执行,在这个方法后面的提交的blocks也必须等待当前block执行完才会操作,该api会立即返回,不会阻塞主线程。

dispatch_queue_t aQueue = dispatch_queue_create("com.wanglei.gcddemo.aQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(aQueue, ^{
        sleep(2);
        NSLog(@"+++++++++++1");
    });
    
    dispatch_async(aQueue, ^{
        NSLog(@"+++++++++++2");
    });
    
    dispatch_barrier_async(aQueue, ^{
        sleep(3);
        NSLog(@"+++++++++++3");
    });
    
    NSLog(@"+++++++++test");
    
    dispatch_async(aQueue, ^{
        NSLog(@"+++++++++++4");
    });

 输出结果如下

2019-04-26 16:58:19.161177+0800 WLTest[15736:1047575] +++++++++test

2019-04-26 16:58:19.161310+0800 WLTest[15736:1047796] +++++++++++2

2019-04-26 16:58:21.166526+0800 WLTest[15736:1049056] +++++++++++1

2019-04-26 16:58:24.167634+0800 WLTest[15736:1049056] +++++++++++3

2019-04-26 16:58:24.167822+0800 WLTest[15736:1049056] +++++++++++4

 可见该方法并没有阻塞主线程,任务4也是在barrier任务完成后才执行的。

需要注意的是这里的队列queue不能使用全局队列,必须是自定义的队列。网上有文章指出该api是可以解决多线程并发读写同一个资源时发生死锁的问题,示例代码如下:

@implementation TicketManager

- (instancetype)init {
    self = [super init];
    
    if (self) {
        self.ticketNumber = 10000;
        saleQueue = dispatch_queue_create("com.wanglei.gcddemo.saleQueue", DISPATCH_QUEUE_CONCURRENT);
    }
    
    return self;
}

- (void)sale:(int)number {
    
    dispatch_barrier_async(saleQueue, ^{
        if (self.ticketNumber == 0) {
            NSLog(@"+++++++++++++++++++++票已售罄");
        } else {
            if (self.ticketNumber >= number) {
                self.ticketNumber -= number;
                NSLog(@"+++++++++++++++售出%d张++++++++++++++还剩%d张",number,self.ticketNumber);
            } else {
                NSLog(@"++++++++++++++++++票数不足,无法完成本次交易");
            }
        }
    });
    
}

@end

       dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block):功能与async类似,但是这个会阻塞主线程,不建议使用。

dispatch_queue_t aQueue = dispatch_queue_crea
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值