进程和线程
基于Win32的应用程序有一个或多个进程组成。进程的一个最简单的术语可以解释为一个可以执行的程序。一个或多个线程可以运行在这个进程的上下文下。一个线程是操作系统分配处理器时间的最基本的单元。一个线程可以在进程的任何地方执行,包含那些已经执行的线程的一部分.一个Fiber是一个必须通过应用程序手工调度的执行单位。Fiber运行在那些调度它们的线程的上下文之下。
一个工作(job)允许一组进程作为一个单元来进行管理的进程组.工作对象(Job object)是可命名的,有安全性,共享性的对象,与它相关的那些进程可以控制它的这些属性。工作对象的有效操作将会影响到与这个工作对象有关的所有进程.
关于进程和线程
每个进程都提供了一些资源用于程序的执行。一个进程具有一个虚地址空间,执行代码段,数据段,对象的句柄,环境变量,基本的优先级别,以及工作区的最大值和最小值。每个进程执行开始都是的从一个单线程开始,这个单线程被称为主线程(primary thread), 通过它可以建立其它附加线程.
一个进程中所有的线程都共享这个进程的虚地址空间和系统资源.除此之外,每个线程都要管理其异常处理,优先级别的调度,以及一组数据结构(系统直到要调度一个线程时,需要保存该线程的上下文相关信息,而为了保存这些信息线程将使用它自己的一组数据结构).线程的上下文包括:该线程的一组机器寄存器,内核栈,一个线程环境块,和在该线程从属的进程地址空间中的一个用户栈.
Window NT / 2000 和 Window 95/98 支持抢先式多任务, 这种方式使得能在多进程下创建有效的同时运行的多线程. 在多处理器的计算机上,Windows NT/2000 可以同时使用多处理器分别执行多个线程.
多任务
在一个多任务操作系统下,系统将会把处理器的时间分割出来,有效的分配给需要处理器资源的多个进程或多个线程. 一个系统被设计为抢先式多任务, 那么它将为每一个线程的执行分配一个处理器时间片(time slice)。 如果当一个正在执行的线程的时间片的时间已经用完(elapse), 那么它将被操作系统挂起(suspended), 这样做是为了另一个线程的运行(下一个等待运行的线程). 当系统在交换线程运行的时候, 操作系统将会把被抢先(被挂起, 被替代)的线程的上下文信息保存起来,同时也会将新获得处理器时间片的线程的上下文信息恢复,以至于新获得时间片的线程能顺利运行.
时间片的长度的定义依赖于操作系统和处理器.由于时间片比较短,大约为20毫妙, 所以多个线程看上去运行是同一时间的(并行的,但其实并不是,不过对与多处理器的系统来说就可能是真正并行的).事实上对于多处理器系统而言那些可执行的线程是分布在不同的有效的处理器上运行的。当你的应用程序使用多线程时必须小心,因为系统性能可能会因为线程的不断增加而减小。
1.多任务的优点
对于用户来说,可以在同一时间打开,运行多个应用程序是多任务的最大优点。例如:一个用户可以通过一个应用程序去修改一个文件,同时另一个应用程序则正在计算电子表格。
对于应用程序开发人员而言, 可以建立一个多进程度的应用程序或多线程的应用程序, 例如, 一个进程可以建立一个用户接口线程用来接受用户的脚互(键盘,鼠标信息), 然后再建立一个工作者线程,在用户正在交互的同时进行它响应的任务.如果用户交互线程的优先级别比工作者线程的高,那么用户交互线程。。。?If you give the user interface thread a higher priority, the application will be more responsive to the user, while the worker threads use the processor efficiently during the times when there is no user input.
2.什么时候使用多任务(When to Use Multitasking)
这里有2种方法可以实现多任务:
(a)单进程多线程
(b)多进程多线程
应用程序可以将给予进程中各自线程需要的私有地址空间和私有资源,并且保证这个进程中的各个线程不得相互作用这些私有地址空间和资源.
一个多线程的进程可以采用互斥独占的方法来管理这些线程,例如提供用户接口线程和执行后台(background)计算. 建立一个多线程进程可以容易的构造一个执行多个相同单一并发任务的程序。
例如,名字管道服务器可以建立一个为每一个刻画进程提供服务的线程,在服务器和客户之间着就存在着线程通讯的管理. 你的进程可以使用多线程完成下面的一些任务:
(a) 管理在多个窗口下输入
(b) 管理多个通讯设备输入
(c) 区分不同优先级别的任务,For example, a high-priority thread manages time-critical tasks, and a low-priority thread performs other tasks.
(d) 允许用户接口任就保持与用户操作的同时也可以分配时间个后台任务
对于是用那些方法实现一个应用程序的多任务性,对与这个应用程序来说是十分高效的。而且使用但单进程多线程比使用多进程还具有更好的高效性。这是因为:
(1)系统在执行上下文交换的时候,线程要比进程快(毕竟进程的上下文信息要比线程多,而且复杂)
(2)一个进程中的所有线程都以共享的方式使用相同地址空间并且可以访问该进程的全局变量,因而这些线程见通信是比较简单的;
(3)一个进程中的所有线程可以共享打开的资源的句柄, 例如文件和管道.
Win32应用程序接口(API)也统共了可选择的方法拥护多线程中.这样一来更加以为着那些方法:(asynchronous input and output (I/O), I/O completion ports, asynchronous procedure calls (APC), and the ability to wait for multiple events.)
一个单线程可以通过使用异步I/O(不同步输入/输出)在并发运行下初始话多个消耗时间(time-consuming)I/O. 异步I/O操作可以在被文件,管道以及串行通信端口设备执行.
当在等待任何一个或所有事间发生的时候,一个单线程可以自己将自己挂起(阻塞,暂停运行)。对于那些等待单个事件发生的多线程来说是非常有高效, 并且性能高过与那些不断检查事件,消耗处理器时间的那种单线程.
3.多任务考虑
有建议说应该尽量少的使用线程,因此可以很少的使用系统资源。这样一来可以改进性能.在你设计应用程序的时候多任务对资源的需求和潜在的冲突需要你认真考虑。资源的需求有下面几项:
(1) 系统将要为所有的进程和线程提供存放上下文信息存放的内存空间,因此大量的进程和线程可以使的建立有效内存变的很受限制(内存使用完,无法为新的应用分配有效存储空间)
(2) 为了可以跟踪大量的线程,要消耗处理器大量工作时间.如果过多的线程,可能会造成程序无反应。如果在一个进程中有太多的当前线程, 因此可能会造成其它进程中的线成很少被调度.
进程中提供的共享资源可能会造成一些访问冲突。为了避免这些冲突,你必须要对这些资源进行同步访问.系统资源(例如:串行通信端口), 多进程共享的那些资源(例如:文件句柄), 单进程中多线程共享的那些资源(例如:全局变量),这些资源都属于可能造成冲突的共享资源.(在同一或不同的进程间)采用同步访问的失败可能回导致一中称为死锁(deadlock)或竞争条件(race conditions)的问题.你可以通过使用Win32 API提供的一系列同步对象和同步函数来协调那些资源在多线程下的合理访问。总而言之,减少线程的数量即可减轻资源同步问题,并且使资源共享变的高效。
对于一个多线程应用程序设计的一个好办法就是管道服务器(pipeline server). 在这样的设计中,
你为每个进程建立一个线程,并且为应用程序上下文信息的请求建立一个队列。一个线程在处理下一个队列的请求之前应该将处理完所有在当前相应队列中的请求.In this design, you create one thread per processor and build queues of requests for which the application maintains the context information. A thread would process all requests in a queue before processing requests in the next queue.