漫谈GCD

本文深入探讨了iOS中的多线程技术,重点关注GCD(Grand Central Dispatch)的使用,包括队列类型、任务提交方式、内存管理以及异步、同步API的运用。通过实例分析了GCD如何简化多线程编程,特别是队列的串行与并行执行,以及如何避免死锁。同时,介绍了延时执行、dispatch_barrier在并发控制中的作用,以及如何通过set_specific与get_specific关联和区分队列。
摘要由CSDN通过智能技术生成

多线程是程序开发中非常基础的一个概念,大家在开发过程中应该或多或少用过相关的东西。同时这恰恰又是一个比较棘手的概念,一切跟多线程挂钩的东西都会变得复杂。如果使用过程中对多线程不够熟悉,很可能会埋下一些难以预料的坑。

iOS中的多线程技术主要有NSThread, GCD和NSOperation。他们的封装层次依次递增,其中:

  • NSThread封装性最差,最偏向于底层,主要基于thread使用

  • GCD是基于C的API,直接使用比较方便,主要基于task使用

  • NSOperation是基于GCD封装的NSObject对象,对于复杂的多线程项目使用比较方便,主要基于队列使用

上篇文章介绍了NSThread的用法,NSThread已经属于古董级别的东西了,欣赏一下可以,真正使用就不要麻烦他了。GCD是多线程中的新贵,比起NSThread更加强大,也更容易使用。由于GCD的东西比较多,我会分好几篇文章介绍,这篇文章主要介绍GCD中的queue相关知识。

dispatch_queue_t

使用GCD之后,你可以不用再浪费精力去关注线程,GCD会帮你管理好一切。你只需要想清楚任务的执行方法(同步还是异步)和队列的运行方式(串行还是并行)即可。

任务是一个比较抽象的概念,表示一段用来执行的代码,他对应到代码里就是一个block或者一个函数。

队列分为串行队列和并行队列:

  • 串行队列一次只能执行一个任务。只有一个任务执行完成之后,下一个任务才能执行,主线程就是一个串行的队列。

687474703a2f2f63646e342e72617977656e6465726c6963682e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031342f30312f53657269616c2d51756575652d343830783237322e706e67.png

  • 并行队列可以同时执行多个任务,系统会维护一个线程池来保证并行队列的执行。线程池会根据当前任务量自行安排线程的数量,以确保任务尽快执行。

687474703a2f2f63646e332e72617977656e6465726c6963682e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031342f30312f436f6e63757272656e742d51756575652d343830783237322e706e67.png

队列对应到代码里是一个dispatch_queue_t对象:

dispatch_queue_t queue;

对象就有内存。跟普通OC对象类似,我们可以用dispatch_retain()和dispatch_release()对其进行内存管理,当一个任务加入到一个queue中的时候,任务会retain这个queue,直到任务执行完成才会release。

值得高兴的是,iOS6之后,dispatch对象已经支持ARC,所以在ARC工程之下,我们可以不用担心他的内存,想怎么玩就怎么玩。

要申明一个dispatch的属性。一般情况下我们只需要用strong即可。

@property (nonatomic, strong) dispatch_queue_t queue;

如果你是写一个framework,framework的使用者的SDK有可能还是古董级的iOS6之前。那么你需要根据OS_OBJECT_USE_OBJC做一个判断是使用strong还是assign。(一般github上的优秀第三方库都会这么做)

#if OS_OBJECT_USE_OBJC
@property (nonatomic, strong) dispatch_queue_t queue;
#else
@property (nonatomic, assign) dispatch_queue_t queue;
#endif

async

GCD中有2个异步的API

void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_async_f(dispatch_queue_t queue, void *context, dispatch_function_t work);

他们都是将一个任务提交到queue中,提交之后立即返回,不等待任务的的执行。提交之后,系统会对queue做retain操作,任务执行完成之后,queue再被release。两个函数实际的功能是一样的,唯一的区别在于dispatch_async接受block作为参数,dispatch_async_f接受函数。

使用dispatch_async的时候block会被copy,在block执行完成之后block再release,由于是系统持有block,所以不用担心循环引用的问题,block里面的self不需要weak

在dispatch_async_f中,context会作为第一个参数传给work函数。如果work不需要参数,context可以传入NULL。work参数不能传入NULL,否则可能发生无法预料的事儿

异步是一个比较抽象的概念,简单的说就是将任务加入到队列中之后,立即返回,不需要等待任务的执行。语言的描述比较抽象,我们用代码加深一下对概念的理解

NSLog(@"this is main queue, i want to throw a task to global queue");
dispatch_queue_t globalQueue = dispatch_queue_create("com.liancheng.global_queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(globalQueue, ^{
    // task
});
NSLog(@"this is ma
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值