在你很小的时候,你学习怎样一次完成一个工作,但到了成年,当然也许你已成为父母辈了,这时,你就必须学会如何在同一时间做多个工作。例如,你是否发现有多少次你在办公室里作弄过电话,E-MAIL 和客人?你也许正在办公室里和一个人在谈话,这时电话铃响了,谈话就被电话打断了。也许正在打电话时,你又来了新(重要的)E-MAIL,你必须中断你的电话。一旦处理完E-MAIL以后,你可以接着打电话或者继续和办公室里的人谈话。如果等的时间太长了,电话另一端的人可能会挂断电话,或者办公室里的人也许会生气离开。你必须决定如何花费你的时间和花在谁身上。
在上面的例子中,你就是在进行多任务处理。你决定如何花费你的时间和计算机对多任务进行时序安排类似。正如我们一天只有24小时,计算机的资源也是有限的。看起来好像你在同时打电话和处理E-MAIL,但事实上,每次你只能将注意力集中在一件事情上。实际上你是在不断变换注意力,只不过变换得足够快,就好像你在同时做多个工作一样。当计算机处理多任务时,它从一个程序到另一个程序的切换是非常快的,以至于使你认为,所有 的程序都在同时运行。
图一,从用户观点看单任务和多任务
假如你有一个克隆(可能叫多莉)的话,你就能同时做两件事。对于有多个CPU的计算机,同时在每一个CPU上运行程序称为多重处理。有时,人们可替换使用多任务处理和多重处理两个概念,但是,你不能在没有多个处理器的计算机上进行多重处理。因此,如果你正在使用一台只有一个处理器的计算机,操作系统可以进行多任务处理,如果你正在使用一台有多个处理器的计算机,操作系统既能进行多任务处理又能进行多重处理。
在操作系统中,过程是一个逻辑上的任务。过程是在运行应用程序,启动某一系统服务,和在Windows NT中启动某一子系统时产生的。每一个过程都有自己的专用资源(例如自己的专用存储空间),只有拥有这个过程的应用程序才能访问这些资源。这意味着,如果你产生了一个程序,在程序中用到一些数据,并且你也没有建立任何形式的程序间数据共享机制或使用操作系统的程序间数据共享机制,那么就只有你的程序能访问这些数据。大多数Windows开发者都用COM对象简化程序间的通信。如果你用的是Windows NT并且想共享数据,你可以使用内存映像文件。但是这对于Geek Speak column来说技术性太强,所以让我们继续往下讲。
多任务处理:合作的和有优先权的
你能使用的多任务处理有两种基本方法:合作的,在这种方法中,正在运行的过程必须为其他过程留出CPU时间片;有优先权的,在这种方法中,操作系统决定哪个程序获得时间片。Microsoft Windows 3.x和Macintosh用的都是合作的多任务处理,而OS/2,Windows 95,Windows NT,UNIX,和Amiga操作系统使用的是有优先权的多任务处理。
合作的多任务处理
如果使用合作的多任务处理,每个程序必须允许其他程序使用CPU。使用合作的多任务处理系统的应用软件都有一个特殊的码环,这个码环产生控制允许其他应用软件的运行。如果每个人都按规则办事,这种方法会工作得相当好,但是当应用程序不服从这一规则时,他“霸占”CPU。这意味着,终端用户不能转向其他应用程序,使操作系统或应用程序出现“挂起”。
有优先权的多任务处理
在有优先权的多任务处理中,操作系统安排CPU时间,一个应用软件在任何时候都有可能被操作系统暂停(先占)。这减轻了“一玩到底”的程序问题,因为操作系统负责分给每个应用软件自己的时间片。
Windows 95对于32位Windows应用程序采用有优先权的多任务处理,为了能够向下兼容,对于16位的Windows应用程序(为Windows 3.x写的应用程序)仍采用合作的多任务处理。
线程
线程是一个能独立于程序的其他部分运行的作业。线程属于一个过程,获得自己的CPU时间片。基于WIN32的应用程序可以使用多个可执行的线程,称为多线程。Windows 3.x不能提供一种机制天然地支持多线程应用程序,但是一些为Windows 3.x编写应用程序的公司使用他们自己的线程安排。
基于WIN32的应用软件能在给定的过程中产生多个线程。依靠生成多个线程,应用程序能够完成一些后台操作,例如计算,这样程序就能运行得更快。当线程运行时,用户仍能继续影响程序。正如前面谈到的,当一个应用程序运行时,就产生了一个相应的过程。那么应用程序就能有一个单独的线程等待键盘输入或执行一个操作,例如脱机打印或计算电子表格中各项的总数。
在网络世界中,当你试图调整你站点的服务器的性能时,就要运行线程。如果你使用的是IIS,你可以在服务器上设置对于每个处理器所能创建的线程的最大数目。这样,就能在处理器间更均匀地分配工作,从而加速你的站点。
线程模式
现在,为了让你知道线程是什么和在哪能使用他们,让我们看一下使用线程时你可能要运行的应用程序:ActiveX组件。ActiveX组件是独立于其他代码运行,基于COM的代码。这听起来是不是很熟悉?当你使用ActiveX组件时,必须在操作系统中注册。其中的一条注册信息就是,这个ActiveX组件是否支持多个线程,如果支持怎样支持。这就是线程模式。
组件支持的基本线程模式有:单线程,单元线程,组合线程。下面几个部分将谈谈每一种模式对组件来说意味着什么。
单线程
如果组件被标记(即注册)为单线程组件,这就意味着所有可执行函数(称作方法)都将在组件的一个共享线程中运行。这就类似于没有生成独立的可执行线程的应用程序。单线程组件的缺点是一次只能运行一个方法。如果多次调用组件,例如调用组件中的存储方法,就会产生瓶颈,因为一次只能有一个调用。
如果你正在创建或使用一个ActiveX组件,建议不要使用单线程组件。
单元线程
如果一个组件被标记为单元线程,那么每个可执行的方法都将在一个和组件相联系的线程上运行。之所以成为单元线程是因为,每个新生成的组件实例都有一个相应的线程单元,每个正在运行的组件都有它自己的线程。单元线程组件要比单线程组件要好,因为多个组件可以在各自的单元中同时运行方法。
自由线程
一个自由线程组件是一个支持多线程单元的多线程组件。这意味着多个方法调用可同时运行,因为每个调用都有自己的运行线程。这能使你的组件运行快得多,但也有一些缺点。运行在同一单元中的单元组件可以在单元中直接调用其他组件的方法,这是一个非常快的操作。但是,自由线程组件必须从一个单元向另一个单元调用。为了实现这一操作,WIN32生成了一个代理,用来通过单元界线。这对于每个需要的功能调用来说就产生了系统开销,从而减低了系统的速度。每一个访问自由组件的调用都有一个相应的代理。既然代理调用比直接调用慢,那么自然会有性能方面的降低。
关于自由线程组件另一个需要注意的是:他们不是真正自由的。如果你创建了一个自由线程组件。你仍必须确保组件中的线程完全同步。这不是一件容易的事。只是简单地把你的组件标记为是自由线程的,并不能使你的组件支持多线程,你仍要去做使你的组件自由线程化的工作。如果你不做这个工作,你的共享数据可能被破坏。这里说明一下为什么:让我们假定你有一个方法计算某个数然后把它写到某个变量中。此方法被传入一个初始值例如是4,在随后的计算中这个变量的值增长为5。在方法结束时这个最后的值被写入到变量中。如果一次只有一个计算过程的话,所有这些会工作得很好。然而,当数据正在被改变时,另一个线程试图访问它,那么重新得到的数据就有可能是错误的。下面的图表说明了这一点。
为了修正这一错误,开发者为对象提供了线程同步。线程同步是在正在运行你想保护的某一其他代码时运行的代码。操作系统并不先占这个代码,直到获得一个可以中断的信号。如果你想了解更多的有关线程同步对象的详细内容,你不应该阅读Geek Speak column!不,我的意思是,“注意看一下本文后面列出的参考阅读文献”。
图二,共享数据被多线程访问搞乱了
组合线程
读到这,你也许会想既然每种形式的线程都有自己的优点和缺点,为什么不把不同的线程模式结合起来使用呢?组合线程模式也许符合你的要求。一个被标记为组合线程的组件既有单元线程组件的特性又有自由线程组件的特性。当一个组件被标记为组合线程时,这个组件将总是在和生成它的对象所在单元相同的单元中创建。如果组件是被一个标记为单线程的对象创建的,那么这个组件的行为将和一个单元线程组件一样,并且它将在线程单元中创建。这就意味着,组件和创建它的对象之间的调用,不需要一个为通信提供的代理调用。
如果新组件是被自由线程组件创建的,那么这个组件将表现得像一个自由线程组件,但是它将在同一单元中运行,因此新组件能够直接访问创建它的对象(既不需代理调用)。切记,如果你打算把你的组件标记为组合线程,你必须提供线程同步保护你的线程数据。
更多的信息
到此为止,你应该对过程,作业,线程有一个基本的了解了。如果你想进一步了解,下面这些文章也许对你有用。我必须事先提醒你,这些资料中的大多数并不是为初学者准备的。很好地理解COM,C++,和WIN32,将会对理解某些文章大有帮助。
Multithreading for Rookies ( http://msdn.microsoft.com/library/techart/msdn_threads.htm) by Ruediger Asche
Windows 95 Resource Kit, Chapter 31 The Windows 95 Architecture, Virtual Machine Manager, Process Scheduling and Multitasking ( http://msdn.microsoft.com/library/winresource/dnwin95/d1c/s72bd.htm)
Understanding and Using COM Threading Models ( http://www.microsoft.com/workshop/components/com/comthread.asp)
Descriptions and Workings of OLE Threading Models ( http://support.microsoft.com/support/kb/articles/q150/7/77.asp)
Fashionable App Designers Agree: The Free-Threading Model is What抯 Hot This Fall ( http://www.microsoft.com/msj/0897/free.htm)
IIS Documentation: Selecting a Threading Mode ( http://msdn.microsoft.com/library/sdkdoc/iisref/eadg2pbg.htm)