进程 线程 协程

进程 线程 协程

这些概念老生常谈了,最近使用了下Lua的协程,查了查资料,又有些新的理解,整理整理。

先上基本概念,以下内容来源于维基百科。

  • 进程
    进程(英语:process),是计算机中已运行程序的实体。进程为曾经是分时系统的基本运作单位。在面向进程设计的系统(如早期的UNIX,Linux2.4及更早的版本)中,进程是程序的基本执行实体;在面向线程设计的系统(如当代多数操作系统、Linux2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。若干进程有可能与同一个程序相关系,且每个进程皆可以同步(循序)或异步(平行)的方式独立运行。现代计算机系统可在同一段时间内以进程的形式将多个程序加载到存储器中,并借由时间共享(或称时分复用),以在一个处理器上表现出同时(平行性)运行的感觉。同样的,使用多线程技术(多线程即每一个线程都代表一个进程内的一个独立执行上下文)的操作系统或计算机体系结构,同样程序的平行线程,可在多CPU主机或网络上真正同时运行(在不同的CPU上)


  • 线程
    线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIXThread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。一个进程可以有很多线程,每条线程并行执行不同的任务。在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行,编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率。


  • 协程
    与子例程一样,协程也是一种程序组件。相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。协程源自Simula和Modula-2语言,但也有其他语言支持。协程更适合于用来实现彼此熟悉的程序组件,如合作式多任务,迭代器,无限列表和管道。


好,官方说明结束,如果你看到这里,还是一脸懵逼的话,那我说说我自己的理解。和上面介绍的顺序一样,先有进程,在有线程,然后是协程,可以这么想象,试着在空间上去理解进程,在时间上去理解线程。

进程给出了一个空间,在这个空间内共享系统资源,内存等,但是进程不具备执行的能力,一个进程至少需要一个主线程来供操作系统调度,实际上真正消耗CPU是线程(当然线程也有自己独立的小空间)在一个进程内,多个线程可以共享这个进程的大空间,那线程与协程区别又是什么呢?

说到系统调度,这个是人为不可控的,多线程之间到底这个时候哪条线程再跑,这是由系统决定的,当有时候我们想自己决定执行顺序以避免一些问题的时候,就产生了锁这个概念,上锁之后顺序是确定了,但是成本增加了。而协程的调度,完全是由用户决定的,无需锁的参与,并且是在一个线程内,自然成本最低,最快,当然缺点也就来了,那就是一个线程内不管你开了多少协程,始终无法真正利用多核CPU,无法做到真正的并发,有利有弊,多线程甚至多进程下在开协程,那自然另说。

在回过来看,各自之间切换的成本 进程 > 线程 > 协程,速度也自然是由慢到快,举个栗子,传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高。可安全性就就反过来了,进程之间一个挂了,对另一个完全没有影响,好比你电脑或者手机上,崩掉一个程序(进程),另外的该是啥样还是啥样,进程是咋崩的,线程执行过程中出错导致的,那这个进程内如果有多个线程,随便一个出错了,别的也别玩了,大空间(进程)都了没了,玩个毛。

总结一下
1. 进程,线程是操作系统级的,协程是语言级的。
2. 每个进程至少包含一个线程,因为线程才是真正的运行单位。
3. 线程进程都是同步机制,而协程则是异步。
4. IO密集型一般使用多线程或者多进程,CPU密集型一般使用多进程,强调非阻塞异步并发的一般都是使用协程,当然有时候也是需要多进程线程池结合的,或者是其他组合方式。

发布于 2018-08-21

文章被以下专栏收录