GCD使用小结

作者: 天心鸥兹 | 来源:发表于2017-09-05 18:19 被阅读14次

    GCD是iOS开发过程当中使用的比较频繁也比较重要的一块,往往项目里涉及到这方面的代码基本都是核心功能,维护的时候都小心翼翼,如果这里出问题给调试带来的难度是较大的。

    下面我就来回顾温习一下GCD有关知识,如有纰漏和不足,欢迎指正。

    本文主要通过一下几个模块来进行总结:

    (1)多线程概念;

    (2)几种多线程编程的优缺点;

    (3) GCD中的几种队列类型;

    (4)GCD中系统提供的常用dispatch方法;

    多线程相关概念

    1. 线程与进程:

    进程:是指程序在计算机上的一次执行过程,例如开启微信,就是开启了一个进程,进程可包含多个线程。

    线程:一组独立执行的代码段,一个线程同时只能执行一个任务,故而多线程并发就是指在同一时间执行多个任务。

    iOS程序中,主线程(又称为UI线程)主要任务就是显示和刷新UI,也只有主线程可以直接修改UI,其他耗时操作会放在子线程(又称为异步线程)处理,这样可以提高程序的执行效率,提高资源的利用率。

    主线程的堆栈大小是1M,其他线程开都是512KB,而且这个值不可更改,这也就意味着只要开启一个线程就会占用一部分内存,线程越多程序的性能也随之降低,所以一般不建议同时开启多个线程。

    2. 线程按照执行方式又可细分:

    同步线程:同步线程会阻塞当前线程然后开始执行该线程内的任务,任务执行完之后才会返回当前线程;

    异步线程:异步线程不会阻塞当前线程,会开启其他线程去执行线程内的任务;

    这里来说下串行和并发的概念:

    串行队列:任务按先后顺序逐个执行,需要等待前一个任务执行完之后才开始执行下一个任务;

    并发队列:多个任务按先后顺序一起开始执行,不用等待前一个任务执行完就可以执行下一个任务,因为任务添加的先后顺序间隔往往忽略不计,所以看起来像是一起执行的。

    并发和并行也是两个不同的概念:并行是基于多核设备的,并行一定是并发,而并发不一定是并行。

    3. 多线程编程中会经常遇到的问题:

    死锁:两个或多个线程都在等待对方完成某个操作才能进行下一步操作,这时候就会发生死锁;

    互斥锁:能够防止多线程抢夺资源造成的数据安全问题,但是需要消耗大量的资源;

    原子属性(atomic)加锁:当属性以atomic修饰时,该属性就能支持互斥锁了,反之若以nonatomic修饰,表示忽略了线程安全;

    上下文切换:当一个进程中有多个线程来回切换时,content switch用来记录执行状态,这是就会产生一些额外的开销。

    几种多线程编程的优缺点

    1. NSThread

    优点:轻量级简单易用,可以直接操作线程对象;

    缺点:需要自己管理线程的生命周期,线程同步;

    2. NSOperation

    优点:基于GCD对GCD的封装,比GCD更加面向对象,不需要关心线程管理;

    缺点:使用时必须使用它的子类;

    3. GCD

    优点:基于C语言更底层更高效,并且不属于cocoa框架,简单易用,效率高,速度快,自动管理线程生命周期;

    缺点:如果遇到较复杂的使用场景,很大可能会遇到死锁问题;

    GCD中的几种队列类型

    Dispatch block的执行最终都会放进某个队列中去执行,GCD中相关函数的创建一般都以dispatch开头:

    (1)Mainqueue主线程串行队列:通过dispatch_get_main_queue来获取;

    (2)Global queue 全局并发队列:通过dispatch_get_global_queue来获取,可以设置优先级;

    (3)Custom queue 自定义队列:通过dispatch_queue_create来获取;

    (4)Groupqueue 组队列:通过dispatch_group_create来获取;

    GCD中系统提供的常用dispatch方法

    1. Dispatch_after 延时添加到队列;

    示例如下:

    Dispatch_after

    从打印信息来看Dispatch_after只是延时提交block,并没有延时后立即执行block,因此它不能实现精确控制。

    2. Diapatch_apply :在给定的队列上多次执行某一任务,在主线程直接调用会阻塞主线程去执行block中的任务,所以一般把它放在异步队列中执行

    示例如下:

    Diapatch_apply

    3. Dispatch_once:保证在app运行期间,block中的代码只执行一次

    比如一个经典的使用场景:单例

    Dispatch_once

    4. Dispatch_barrier_async :栅栏作用

    在并发队列中,等待在Dispatch_barrier之前加入的队列全部执行完,再执行Dispatch_barrier中的任务,执行完之后再开始执行Dispatch_barrier之后加入到队列的任务。

    示例如下:

    Dispatch_barrier_async

    相关文章

      网友评论

        本文标题:GCD使用小结

        本文链接:https://www.haomeiwen.com/subject/gtkpjxtx.html