简述进程、线程、协程的概念

进程

  • 保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,不同进程间可以进行进程间通信,上级挂靠单位是操作系统。一个应用程序相当于一个进程,操作系统会以进程为单位,分配系统资源(CPU 时间片、内存等资源),进程是资源分配的最小单位。

线程

  • 线程从属于进程,也被称为轻量级进程,是程序的实际执行者。线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条- 线程并行执行不同的任务。一个线程只有一个进程。

  • 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

  • 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。

协程

  • 协程是伴随着主线程一起运行的一段程序。

  • 协程与协程之间是并行执行,与主线程也是并行执行,同一时间只能执行一个协程提起协程,自然是要想到线程,因为协程的定义就是伴随主线程来运行的。

  • 一个线程可以拥有多个协程,协程不是被操作系统内核所管理,而完全是由程序所控制。

  • 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。

  • 协成是单线程下由应用程序级别实现的并发。

简述协程的作用

  • 在Unity中只有主线程才能访问Unity3D的对象、方法、组件。当主线程在执行一个对资源消耗很大的操作时,在这一帧我们的程序就会出现帧率下降,画面卡顿的现象!

  • 那这个时候我们就可以利用协程来做这件事,因为协程是伴随着主线程运行的,主线程依旧可以丝滑轻松的工作,把脏活累活交给协程处理就好了!简单来说:协程是辅助主线程的操作,避免游戏卡顿。

简述协程的底层原理

  • 协程是通过迭代器来实现功能的,通过关键字IEnumerator来定义一个迭代方法。

  • StartCoroutine 接受到的是一个 IEnumerator ,这是个接口,并且是枚举器或迭代器的意思。

  • yield 是 C#的一个关键字,也是一个语法糖,背后的原理会生成一个类,并且也是一个枚举器,而且不同于 return,yield 可以出现多次。

  • yield 实际上就是返回一次结果,因为我们要一次一次枚举一个值出来,所以多个 yield 其实是个状态模式,第一个 yield 是状态 1,第二个 yield 是状态 2,每次访问时会基于状态知道当前应该执行哪一个 yield,取得哪一个值。

从程序的角度讲,协程的核心就是迭代器。 想要定义一个协程方法有两个因素:
第一: 方法的返回值为 IEnumerator 。
第二: 方法中有 yield 关键字。 当代码满足以上两个条件时,此方法的执行就具有了迭代器的特质,其核心就是 MoveNext方法。

方法内的内容将会被分成两部分:yield 之前的代码和 yield 之后的代码。
yield之前的代码会在第一次执行MoveNext时执行, yield之后的代码会在第二次执行MoveNext方法时执行。

而在Unity中,MoveNext 的执行时机是以帧为单位的,无论你是设置了延迟时间,还是通过按钮调用 MoveNext ,亦或是根本没有设置执行条件,Unity都会在每一帧的生命周期中判断当前帧是否满足当前协程所定义的条件,一旦满足,当前帧就会抽出CPU时间执行你所定义的协程迭代器的 MoveNext 。

注意,只要方法中有 yield 语句,那么方法的返回值就必须是 IEnumerator ,不然无法通过编译。

线程与协程的区别

  • 协程:即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。协程实际上是在一个线程中,只不过每个协程对CPU进行分时,协程可以访问和使用unity的所有方法和component。同一时间只能执行某个协程。开辟多个协程开销不大。协程适合对某任务进行分时处理。

  • 线程:多线程是阻塞式的,每个IO都必须开启一个新的线程,但是对于多CPU的系统应该使用thread,尤其是有大量数据运算的时刻,但是IO密集型就不适合;而且thread中不能操作unity的很多方法和component。同一时间可以同时执行多个线程。开辟多条线程开销很大。线程适合多任务同时处理。

  • 线程和协同程序的主要不同在于:在多处理器情况下,从概念上来讲多线程程序同时运行多个线程;而协同程序是通过协作来完成,在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只在必要时才会被挂起。

协同程序 有何用处? 有何缺点?

作用

  1. 一个协同程序在执行过程中,可以在任意位置使用 yield 语句。
  2. yield 的返回值控制何时恢复协同程序向下执行。
  3. 协同程序在对象自有帧执行过程中堪称优秀。
  4. 协同程序在性能上没有更多的开销。

缺点

  • 协同程序并非真线程,可能会发生堵塞。