进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的聚集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。php
线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程由几个线程组成(拥有不少相对独立的执行流的用户程序共享应用程序的大部分数据结构),线程与同属一个进程的其余的线程共享进程所拥有的所有资源。算法
"进程——资源分配的最小单位,线程——程序执行的最小单位"编程
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不一样执行路径。线程有本身的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,因此多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行而且又要共享某些变量的并发操做,只能用线程,不能用进程。浏览器
总的来讲就是:进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)。(下面的内容摘自Linux下的多线程编程)服务器
使用多线程的理由之一是和进程相比,它是一种很是"节俭"的多任务操做方式。咱们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,创建众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工做方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程间彼此切换所需的时间也远远小于进程间切换所须要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,固然,在具体的系统上,这个数据可能会有较大的区别。数据结构
使用多线程的理由之二是线程间方便的通讯机制。对不一样进程来讲,它们具备独立的数据空间,要进行数据的传递只能经过通讯的方式进行,这种方式不只费时,并且很不方便。线程则否则,因为同一进程下的线程之间共享数据空间,因此一个线程的数据能够直接为其它线程所用,这不只快捷,并且方便。固然,数据的共享也带来其余一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最须要注意的地方。多线程
除了以上所说的优势外,不和进程比较,多线程程序做为一种多任务、并发的工做方式,固然有如下的优势:并发
线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通信)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。函数
进程拥有这许多共性的同时,还拥有本身的个性。有了这些个性,线程才能实现并发性。这些个性包括:spa
1.线程ID
每一个线程都有本身的线程ID,这个ID在本进程中是惟一的。进程用此来标
识线程。
2.寄存器组的值
因为线程间是并发运行的,每一个线程有本身不一样的运行线索,当从一个线
程切换到另外一个线程上 时,必须将原有的线程的寄存器集合的状态保存,以便
未来该线程在被从新切换到时能得以恢复。
3.线程的堆栈
堆栈是保证线程独立运行所必须的。
线程函数能够调用函数,而被调用函数中又是能够层层嵌套的,因此线程
必须拥有本身的函数堆栈, 使得函数调用能够正常执行,不受其余线程的影
响。
4.错误返回码
因为同一个进程中有不少个线程在同时运行,可能某个线程进行系统调用
后设置了errno值,而在该 线程尚未处理这个错误,另一个线程就在此时
被调度器投入运行,这样错误值就有可能被修改。
因此,不一样的线程应该拥有本身的错误返回码变量。
5.线程的信号屏蔽码
因为每一个线程所感兴趣的信号不一样,因此线程的信号屏蔽码应该由线程自
己管理。但全部的线程都 共享一样的信号处理器。
6.线程的优先级
因为线程须要像进程那样可以被调度,那么就必需要有可供调度使用的参
数,这个参数就是线程的 优先级。
Nginx 是非阻塞IO & IO复用模型,经过操做系统提供的相似 epoll 的功能,能够在一个线程里处理多个客户端的请求。
Nginx 的进程就是线程,即每一个进程里只有一个线程,但这一个线程能够服务多个客户端。
PHP-FPM 是阻塞的单线程模型,pm.max_children 指定的是最大的进程数量,pm.max_requests 指定的是每一个进程处理多少个请求后重启(由于 PHP 偶尔会有内存泄漏,因此须要重启).
PHP-FPM 的每一个进程也只有一个线程,可是一个进程同时只能服务一个客户端。
Linux 下相对来讲建立多进程的开销比较小(写时复制,但也比建立多线程昂贵),而 Linux 的线程功能又不是很强大。使用进程主要是由于采用非阻塞与I/O复用,能够带来比多线程更高的效率,可是代码逻辑会更复杂(参考UNPv1)。
可是有的状况,好比浏览器若是也所有使用多进程技术,那么进程数会特别多,这时须要线程进程协做方式,好比chromium浏览器:http://blog.csdn.net/talking12391239/article/details/19755997
什么时候选用多进程,多线程呢,犹以下经验:
1)须要频繁建立销毁的优先用线程
缘由请看上面的对比。
这种原则最多见的应用就是Web服务器了,来一个链接创建一个线程,断了就销毁线程,要是用进程,建立和销毁的代价是很难承受的
2)须要进行大量计算的优先使用线程
所谓大量计算,固然就是要耗费不少CPU,切换频繁了,这种状况下线程是最合适的。
这种原则最多见的是图像处理、算法处理。
3)强相关的处理用线程,弱相关的处理用进程
什么叫强相关、弱相关?理论上很难定义,给个简单的例子就明白了。
一 般的Server须要完成以下任务:消息收发、消息处理。“消息收发”和“消息处理”就是弱相关的任务,而“消息处理”里面可能又分为“消息解码”、“业 务处理”,这两个任务相对来讲相关性就要强多了。所以“消息收发”和“消息处理”能够分进程设计,“消息解码”、“业务处理”能够分线程设计。
固然这种划分方式不是一成不变的,也能够根据实际状况进行调整。
4)可能要扩展到多机分布的用进程,多核分布的用线程
缘由请看上面对比。
5)都知足需求的状况下,用你最熟悉、最拿手的方式
至于“数据共享、同步”、“编程、调试”、“可靠性”这几个维度的所谓的“复杂、简单”应该怎么取舍,没有明确的选择方法。但能够根据一个选择原则:若是多进程和多线程都可以知足要求,那么选择最熟悉、最拿手的那个。
须要提醒的是:虽然给了这么多的选择原则,但实际应用中基本上都是“进程+线程”的结合方式,千万不要真的陷入一种非此即彼的误区。