美文网首页
我所理解的GCD知识

我所理解的GCD知识

作者: 雨天多久就 | 来源:发表于2017-11-28 18:51 被阅读29次

多线程


谈到多线程,一般都会有个疑问:

线程是什么?而谈到线程,不可避免的就是会谈到另外一个词:进程。那么,什么是线程?什么是进程?两者的区别和联系?

  • 进程:是系统资源分配和调度的独立单位
  • 线程:我的理解就是线程是CPU调度和分派的基本单位

举个例子:现在有一个工厂,这个工厂有三个车间:车间A,B和C,每个车间都有4台机器。A负责生产鞋带,B负责生产鞋底,C负责生产鞋身。现在我们收到了一批订单,要生产1000双鞋。那开始生产的时候,就是车间为一个单位,获取资源开始工作,每个车间里,又分派给4台机器开始去工作进行生产。
在这里,车间就类似我们的进程。车间里的线程就是我们的线程。

因此,我们可以知道,一个进程里至少得有一条线程才可以工作。

使用多线程的好处是:可以充分利用CPU的资源进行并发工作


现在来看看iOS里面的多线程

iOS里面使用多线程主要是两种途径GCD和NSOpeartionQueue

GCD 是苹果对C语言线程的封装,使用还是利用c语言的函数来,据说特点是能够高效的利用设备的性能

NSOpeartionQueue 是苹果对GCD的封装,封装成大家熟悉的对象,直接用对象语言去操作

这里我们主要是介绍GCD

要了解GCD,首先需要了解的是四个概念:同步函数,异步函数,并发队列和串行队列

  • 同步函数 dispatch_sync 开头的函数。特点是需要这个函数的代码执行完毕,后面的代码才可以进行

  • 异步函数 dispatch_async 开头的函数。特点是后面的代码不需要等待这个函数的代码执行完毕,可以同时进行

  • 并发队列 队列里的任务可以并发执行

    并发队列的获取方式有两种:
    1.通过dispatch_queue_create函数创建

     dispatch_queue_t   queue = dispatch_queue_create("first_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
    

    2.通过dispatch_get_global_queue函数可以获取系统提供的全局并发队列

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0)

  • 串行队列 队列里的任务是一个接一个执行的

串行队列的获取方式也有两种:1.通过dispatch_queue_create函数创建。 2.通过dispatch_get_main_queue函数可以获取系统提供的主队列

1.通过dispatch_queue_create函数创建
dispatch_queue_t queue = dispatch_queue_create("first_serial_queue", DISPATCH_QUEUE_DISPATCH_QUEUE_SERIAL);

2.通过dispatch_get_main_queue()函数可以获取系统提供的主队列
dispatch_queue_t queue = dispatch_get_main_queue()

这个主队列比较重要,也比较特殊。主队列里,只有一条主线程,一般情况下,在整个APP中,大部分的操作都是在这条线程上。UI控件的更新和行为都要在这个线程上执行。因此,它也叫UI线程。

在GCD里,主要是利用这四个进行组合使用,下面我们一个一个来看

  • 同步并发队列

    同步并发

    首先touchesBegan方法是在主线程执行的。从输出可以看到,同步并发队列并不会创建新的子线程,四个个任务都是顺序执行的。

  • 同步串行队列

    同步串行

    从输出看,同步串行队列也不会创建新的子线程来执行任务,并且四个任务也是顺序执行的

  • 异步并发队列

    异步并发

    从输出看,异步并发队列创建了三条线程。因为是异步执行的缘故,输出语句按照逻辑上应该是无序的。个人认为之所以end这条语句先输出,是因为异步操作开辟线程耗费了一点点时间。如果三个任务里执行的是耗时操作,那输出语句就是看哪个任务先执行完成。

  • 异步串行队列

    异步串行

    从输出结果看,异步串行,也创建了一条子线程。三个任务都是在这一条子线程上执行。逻辑上三个任务是有序的。

总结

队列 同步 异步
并发队列 不会创建子线程,顺序执行 会创建多条子线程,任务之间是并发执行
串行队列 不会创建子线程,顺序执行 只会创建一条子线程,子线程上的任务顺序执行
主队列 不会创建子线程,顺序执行 不会创建子线程,任务在主线程上顺序执行

其他函数

dispatch_group 参考来源

是可以将多个任务放在一个任务组里,进行统一的管理

  • dispatch_group_async(group, queue, block)将block任务添加到queue队列,并被group组管理
  • dispatch_group_enter(group)声明dispatch_group_enter(group)下面的任务由group组管理,group组的任务数+1
  • dispatch_group_leave(group)相应的任务执行完成,group组的任务数-1
  • dispatch_group_create()创建一个group组
  • dispatch_group_wait(group1, DISPATCH_TIME_FOREVER)
    当前线程暂停,等待dispatch_group_wait(group1, DISPATCH_TIME_FOREVER)上面的任务执行完成后,线程才继续执行
  • dispatch_group_notify(group1, queue1,block)
    监听group组中任务的完成状态,当所有的任务都执行完成后,触发block块,执行总结性处理。

dispatch_group的使用

dispatch_group_async(group,queue,block)dispatch_group_notify(group,queue,block)组合使用。

同步任务和异步任务

同步任务

输出语句hahahaha会等上面的所有任务都完成了,才会去执行。

异步任务
可以看到,因为里面的任务都是异步执行的,这个时候hahahaha不会等待上面所有的任务完成。

dispatch_group_enter(group) dispatch_group_leave(group)dispatch_group_notify(group1, queue1,block) 组合使用

dispatch_group_enter(group)
dispatch_async(queue, ^{
            sleep(3);
            NSLog(@"====second=====%@",[NSThread currentThread]);
        });
dispatch_group_leave(group)

dispatch_group_async(group, queue, ^{
        dispatch_async(queue, ^{
            sleep(3);
            NSLog(@"====second=====%@",[NSThread currentThread]);
        });
    });

作用是一样的。两种写法而已。


栅栏函数 dispatch_barrier_

作用是可以等这个队列里的任务都完成的时候做一个操作。


栅栏异步
栅栏同步

注意:栅栏函数使用的queue,必须是并行队列,并且不能是系统提供的并发队列

dispatch_apply 快速迭代

快速迭代

利用多线程进行的快速循环,循环次数多的情况下,更加快速。

dispatch_sem 信号量

信号量就是一个资源计数器,对信号量有两个操作来达到互斥,分别是P和V操作。 一般情况是这样进行临界访问或互斥访问的: 设信号量值为1, 当一个进程1运行是,使用资源,进行P操作,即对信号量值减1,也就是资源数少了1个。这是信号量值为0。系统中规定当信号量值为0是,必须等待,知道信号量值不为零才能继续操作。 这时如果进程2想要运行,那么也必须进行P操作,但是此时信号量为0,所以无法减1,即不能P操作,也就阻塞。这样就到到了进程1排他访问。 当进程1运行结束后,释放资源,进行V操作。资源数重新加1,这是信号量的值变为1. 这时进程2发现资源数不为0,信号量能进行P操作了,立即执行P操作。信号量值又变为0.次数进程2咱有资源,排他访问资源。 这就是信号量来控制互斥的原理

作者:纸简书生
链接:http://www.jianshu.com/p/04ca5470f212
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

信号量使用

写在最后-多线程不好的地方

  • 使用不好,会造成死锁问题

    最经典的例子:


    死锁问题

    问题分析:首先touchBegan方法肯定是在主线程执行的。然后我们是在方法里面,进行了一个同步的函数任务,因为是同步任务,那么主线程就要等这个任务结束了,才往后面走。但是这个任务是会被主队列加到主线程里执行,然而这个时候主线程里正在执行touchBegan这个任务,只有等这个任务结束了,才能执行其他的。因此双方就都在等待,造成死锁问题。

    解决方法很简单:既然是双方相互等待造成的问题,那只要让一方不等就行了。这个任务可以执行在其他线程就行了或者不使用同步函数,使用异步函数

  • 多线程使用,肯定会有线程安全问题(访问临界资源)

    这个就不过多说了,类似的问题很多,比如买票什么的

相关文章

  • 我所理解的GCD知识

    多线程 谈到多线程,一般都会有个疑问: 线程是什么?而谈到线程,不可避免的就是会谈到另外一个词:进程。那么,什么是...

  • GCD相关知识点

    GCD相关知识点 多线程技术--GCD 深入学习GCD GCD 深入理解:第一部分 GCD 深入理解:第二部分 1...

  • iOS笔记--GCD相关知识

    GCD相关知识 1.GCD(Grand Central Dispatch)教程 2.GCD 深入理解:第一部分 备...

  • 我所理解的知识管理

    我学习知识管理的收获 假日期间,花了差不多一天半的时间重新整理了过往一年左右积累的印象笔记文档,并仔细阅读了知识管...

  • GCD串行并发队列

    学习完本篇,您会对以下知识点更加理解: 队列 串行队列 并发队列 GCD全局队列 GCD主队列 创建串行队列 创建...

  • 我理解的GCD

    一、前期准备 GCD中有这么几个概念:同步派发sync、异步派发async、串行队列、并行队列。大家应该都听过这几...

  • 聊聊我所理解的知识付费

    接触知识付费是在2016年,那时在健身房做健身教练,在给顾客服务的过程中,发现很多问题而自己没有能力解决。比如体态...

  • GCD 中的线程组 Group

    前言 本文主要介绍 GCD 中的线程组 Group,不讲 GCD 基础概念知识。如果对 GCD 的基本知识点不是很...

  • 一 GCD初识

    1.GCD基础概念(此笔记为学习Objective-C高级编程书中第三章所记录的相关知识点) gcd为异步执行任务...

  • 关于GCD的dispatch_group_t

    知识储备:了解GCD,理解queue--队列和block--任务概念 1.dispatch_group_t概念 d...

网友评论

      本文标题:我所理解的GCD知识

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