http://www.nowamagic.net/librarys/veda/detail/1741进程和线程这对概念的理解也是很难的,至今网络上可查的资料对其的理解出入都挺大,在不同的操作系统中,如linux和windows中,其概念和实现都是有出入的。因此,我在这里结合我自己的理解谈下这两个概念,讲的都是一般性的概念,并且主要是基以WINDOWS的。
一般将进程定义为一个正在运行的程序的实例。我们在任务管理器重所看到的每一项,就可以理解为一个进程,每个进程都有一个地址空间,这个地址空间里有可执行文件的代码和数据,以及线程堆栈等。一个程序至少有一个进程。进程可以创建子进程,创建的子进程可以和父进程一起工作,也可以独立运行。
而线程是隶属于进程的,也就是说,线程是不能单独存在的,线程存在于进程中。每个进程至少有一个主线程,进程里的线程就负责执行进程里的代码,这也叫做进程的“惰性”。线程所使用的资源是它所属的进程的资源。线程也有自己的资源,主要组成部分就是一些必要的计数器和线程栈,占用的资源很少。我们可以理解为进程就是个容器,而线程才是真正干活的。线程可以在内核空间实现,也可以在用户空间实现。
这里特别提一下linux,在linux中,每一个进程都必须有一个父进程(如果没有父进程,则把PID=1的根进程作为其父进程)。进程退出了,就成了僵尸进程,等待父进程的退出信号,如果父进程没有给他发信号,得给他找一个父进程,或者等待内核自动销毁。Linux内核只提供了轻量进程的支持,限制了更高效的线程模型的实现,但Linux着重优化了进程的调度开销,使得linux进程切换开销较小。所以linux系统没有真正意义上的线程机制。linux中,Linux线程是通过进程来实现,进程和线程是同一个层次的。(我这里提到的是基于linux 2.6 内核的,在最新的LINUX中,对线程的实现做了优化,但是还是基于进程的。有些linux实现了新的线程机制,但主流还是和我描述的一样)
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这也是进程和线程的重要区别。
比如,windows中的explorer就是资源管理器进程,我们每打开一个窗口,这个进程就会创建一个线程。有上面的描述,我们可以知道,进程有独立的地址空间,多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
在第一节中,我提到过,“并发!=多线程“,是的。如Unix操作系统和Windows操作系统支持多用户、多进程的并发执行,而Java这样的语言支持应用程序进程内部的多个执行线程的并发执行。我们知道,php在语法上是没有多线程这个概念的,那java/NET的多线程是怎么实现的。实际上,java只是通过native方法调用操作系统API来创建多线程而已。另外,我们经常说某个网站并发是多少多少,nginx是高并发服务器了。这里的并发和我前面的并发概念是不同的。要想做到高并发,除了多线程等的实现,还需要各种好的IO机制,不然线程再多也没用,资源利用跟不上来。高并发又跟同步、异步等IO复用机制有了牵连。
下面列举一下进程和线程中的一些概念。
- 进程:创建,销毁,创建子进程(fork),优先级。
- 线程:创建,挂起,恢复,销毁,切换,协作,睡眠,唤醒,等待,同步,锁,优先级。
从上面的描述,基本可以理清进程和线程的关系了。最后总结下:
- linux没有内核上的多线程实现,但是不能说linux没有多线程。WINDOWS有内核的多线程实现。
- 进程开销大,线程开销小,但是linux的进程和线程开销差异不明显。
- 并行的实现离不开多线程。
再留个悬念,多线程的实现和运行还会涉及到同步异步,原子性等概念。这些概念是相互交叉的,这里先不做深入。