进程是一个具备必定独立功能的程序关于某次数据集合的一次运行活动,它是操做系统分配资源的基本单元。它能够申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不仅是程序的代码,还包括当前的活动,经过程序计数器的值和处理寄存器的内容来表示。进程的概念主要有两点:第一,进程是一个实体。每个进程都有它本身的地址空间,通常状况下,包括文本段、数据段和堆栈段。文本段存储处理器执行的代码;数据段储变量和进程执行期间使用的动态分配的内存;堆栈段存储着活动过程调用的指令和本地变量。第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操做系统执行之),它才能成为一个活动的实体,咱们称其为进程。多线程
线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组 成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程本身不拥有系统资源,只拥有一点儿在运行中必不可少的资源,每个程序都至少有一个线程,若程序只有一个线程,那就是程序自己。并发
协程是一种编译器级实现的用户态的轻量级线程,本质上讲只是线程的一种实现。相对于线程,协程也相对独立,有本身的上下文,可是其切换由程序本身控制。函数
以上是抽象概念,它们的特性也很大程度取决于具体实现(操做系统或者编译器)。好比LINUX的线程实现就和WINDOWS有很大不一样,LINUX的线程实际上是轻量级进程(Light Weight Process,LWP),GO的协程也和C#的协程不一样。性能
若是把进程比做工厂里的一个车间,车间里有各类的原材料,设备,和工做人员等等。那么线程就是车间里的生产线,它们负责整个车间的生产工做,共享车间内的其它资源,一个车间最少有一个生产线,也能够有多个。协程就好像是生产线里更小的生产单位,可以被一些阀门控制。操作系统
从概念上看,协程实际上是线程的一种实现,因此能够先简单的认为协程就是线程的一种。而多进程和多线程程序却有着比较大的区别。线程
在WINDOWS和LINUX下的进程建立不太同样。指针
LINUX的fork()是函数经过系统调用建立一个与原来进程几乎彻底相同的进程,exec()则是用来启动另外的进程以取代当前运行的进程,一个进程一旦调用exec类函数,它自己就"死亡"了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,惟一留下的,就是进程号。协程
WINDOWS则是用CreateProccess()来建立一个新的进程,这个新进程运行指定的可执行文件,看上去效果和LINUX的fork()+exec()差很少,只是实现上不太相同。blog
将多个用户级线程映射到一个内核级线程,线程管理在用户空间完成,这种模型下操做系统并不知道多线程的存在。如的GO(1.5之前)就是这种模型。
优势:线程管理是在用户空间进行的,切换上下文开销比较小,性能较高。
缺点:当一个线程在使用内核服务时被阻塞,那么整个进程都会被阻塞;多个线程不能并行地运行在多处理机上。队列
将每一个用户级线程映射到一个内核级线程。Java的线程就属于这种模型。
优势:当一个线程被阻塞后,容许另外一个线程继续执行,因此并发能力较强;能很好的利用到CPU的多核心。
缺点:每建立一个用户级线程都须要建立一个内核级线程与其对应,这样建立线程的开销比较大,会影响到应用程序的性能。而且切换线程要进出内核,代价比较大。
将n个用户级线程映射到m个内核级线程上,要求 m <= n。GO(1.5以后)的协程就属于这种线程模型。
特色:既克服了多对一模型的并发度不高的缺点,又克服了一对一模型的一个用户进程占用太多内核级线程,开销太大的缺点。又拥有多对一模型和一对一模型各自的优势。
进程间是彻底独立的个体,多进程环境中,任何一个进程终止不会影响其余进程,而多线程环境中任何一个线程执行exit系统调用,则全部线程退出,最多见的是因某个线程异常致使程序的退出。
通讯方式,进程间通讯(IPC:无名管道,有名管道,消息队列,信号,信号量,共享内存等)较为复杂,线程间能够直接读写进程数据段(如全局变量)来进行通讯(须要线程同步和互斥手段的辅助,以保证数据的一致性)。
线程比进程轻,不论是建立仍是上下文切换,线程的开销都要比进程小。