多线程与GCD执行原理
声名 此文章内容 整理自
[link](http://www.cocoachina.com/bbs/read.php?tid-459704.html)
[link](https://www.cnblogs.com/ziyi--caolu/p/4846555.html)
这两篇讲解特别到位,个有所长,十分符合胃口
情不自禁整理到自己这里,日日观摩。
侵删
GCD 含义
可以生成必要的线程并计划执行任务
实现原理
- GCD有一个底层线程池,这个池中存放的是一个个的线程。之所以称为“池”,很容易理解出这个“池”中的线程是可以重用的,当一段时间后这个线程没有被调用胡话,这个线程就会被销毁。注意:开多少条线程是由底层线程池决定的(线程建议控制再3~5条),池是系统自动来维护,不需要我们程序员来维护
- 如果队列中存放的是同步任务,则任务出队后,底层线程池中会提供一条线程供这个任务执行,任务执行完毕后这条线程再回到线程池。这样队列中的任务反复调度,因为是同步的
- 如果队列中存放的是异步的任务,(注意异步可以开线程),当任务出队后,底层线程池会提供一个线程供任务执行,因为是异步执行,队列中的任务不需等待当前任务执行完毕就可以调度下一个任务,这时底层线程池中会再次提供一个线程供第二个任务执行,执行完毕后再回到底层线程池中
-这样就对线程完成一个复用,而不需要每一个任务执行都开启新的线程,也就从而节约的系统的开销,提高了效率。在iOS7.0的时候,使用GCD系统通常只能开5~8条线程,iOS8.0以后,系统可以开启很多条线程,但是实在开发应用中,建议开启线程条数:3-5条最为合理
名词解释
- 串行(Serial)与 并发(Concurrent)
- 任务串行,意味着在同一时间,有且只有一个任务被执行,即一个任务执行完毕之后再执行下一个任务。
- 任务并发,意味着在同一时间,有多个任务被执行。
- 同步(Synchronous)与 异步 (Asynchronous)
- 同步,意味着在当前线程中执行任务,不具备开启新的线程的能力。
- 异步,在新的线程中执行任务,具备开启新的线程的能力。
- 临界区(Critical Section)
- 就是一段代码不能被并发执行,也就是,两个线程不能同时执行这段代码。这很常见,因为代码去操作一个共享资源,例如一个变量若能被并发进程访问,那么它很可能会变质(它的值不再可信)。
- 死锁(Deadlock)
- 停止等待事情的线程会导致多个线程相互维持等待,即死锁。
两个(有时更多)东西——在大多数情况下,是线程——所谓的死锁是指它们都卡住了,并等待对方完成或执行其它操作。第一个不能完成是因为它在等待第二个的完成。但第二个也不能完成,因为它在等待第一个的完成。
- 线程安全(Thread Safe)
- 线程安全的代码能在多线程或并发任务中被安全的调用,而不会导致任何问题(数据损坏,崩溃,等)。线程不安全的代码在某个时刻只能在一个上下文中运行。一个线程安全代码的例子是 NSDictionary 。你可以在同一时间在多个线程中使用它而不会有问题。另一方面,NSMutableDictionary 就不是线程安全的,应该保证一次只能有一个线程访问它。
- 上下文切换(Context Switch)
- 一个上下文切换指当你在单个进程里切换执行不同的线程时存储与恢复执行状态的过程。这个过程在编写多任务应用时很普遍,但会带来一些额外的开销。
- 并发与并行
- 并行要求并发,但并发不能保证并行,就计算机操作系统来说,开启线程是很耗性能的,也就是说,事实上,在某次并行处理任务中,开启的线程是有上限的,如果上限为2,即每次开启的新线程为2,那么是有可能出现并发却不并行的情况。
- 并发代码的不同部分可以“同步”执行。然而,该怎样发生或是否发生都取决于系统。多核设备通过并行来同时执行多个线程;然而,为了使单核设备也能实现这一点,它们必须先运行一个线程,执行一个上下文切换,然后运行另一个线程或进程
- 队列 与 任务
- 队列 只是负责任务的调用,不负责任务的执行
- 任务 是在线程中执行的
- 队列和任务的特点
- 队列的特点:先进先出,排在前面的任务最先执行.
- 串行队列:任务按照顺序被调度,前一个任务不执行完毕,队列不会调度.
- 并行队列:只要有空闲的线程,队列就会调度当前任务,交给线程去执行,不需要考虑前面是都有任务在执行,只要有线程可以利用,队列就会调度任务.
- 主队列:专门用来在主线程调度任务的队列,所以主队列的任务都要在主线程来执行,主队列会随着程序的启动一起创建,我们只需get即可
- 全局队列:是系统为了方便程序员开发提供的,其工作表现与并发队列一致,那么全局队列跟并发队列的区别是什么呢?
- 要考录释放,因为系统提供的我们只需要get就可以了
- 并发队列:再MRC下,并发队列创建出来后,需要手动释放dispatch_release()
- 任务特点
- 同步执行:不会开启新的线程,任务按顺序执行
- 异步执行:会开启新的线程,任务可以并发的执行
GCD执行过程
- 串行队列
- 唯一能确保的事情是 GCD 一次只执行一个任务,并且按照我们添加到队列的顺序来执行。开辟了一个新的子线程,任务是按顺序执行的。先进先出顺序执行的。因为要等待前一个任务处理结束,即同一时间,只能处理一个任务,才可以开始处理下一任务。
- 并发队列
- 在并发队列中的任务能得到的保证是它们会按照被添加的顺序开始执行,但这就是全部的保证了。任务可能以任意顺序完成,你不会知道何时开始运行下一个任务,或者任意时刻有多少 Block 在运行。所谓“并行执行”,就是使用多个线程同时处理多个任务,因为完成任务所需要消耗的时间不同,所以完成任务的最终时间不同。