《Windows游戏编程大师技巧》(第二版)第11章(20) 图11-15:标准DOS单任务游戏循环 由图11-15中可知,游戏逻辑以串行(顺序)方式来完成各项任务。当然也有例外,比如通过中断来完成一些简单的逻辑任务,诸如音乐、输入控制等。但总地说来,游戏就是一个长长的函数调用序列。尽管每一项任务都是顺序执行,但由于计算机足够快,其执行的结果就如同同时发生一般,这样便使游戏看上去非常流畅和真实。所以,大多数游戏程序是一个单任务执行线程——顺序执行一些操作并输出每一帧所需要的结果。这是解决问题最好的方法之一,也是DOS游戏编程的必然结果。然而在今天,DOS时代已成为过去,所以现在是发挥Windows 95/98/ME/XP/NT/2000多线程威力的时候了,我打赌你会喜欢的!这节内容将就Windows 95/98/NT下的执行线程(thread of execution)进行探讨。通过使用线程可以轻易地在一个应用程序中运行多个任务。在开始之前,让我们先看一些术语,这样提到它们的时候不会太突兀。多线程编程的术语在计算机词典里有各种各样以“multi-”开头的词语。让我们先谈一谈多处理器(Multiprocessor)和多重处理(Multiprocessing),最后再讨论多线程(multithreading)。一台多处理器计算机是指具有多个处理器的计算机。Cray和Connection Machine就属于这类。Connection Machine计算机可以安装多达64000个处理器(构成一个超立方体网络),其中每一个处理器均用于执行代码。对一般消费者而言,购买配置有四个PIII+处理器的计算机用于运行Windows NT可能比较实际。通常它们都是SMP(对称多处理,Symmetrical Multiprocessing)系统,即四个处理器可以对称地执行任务。实际上,情况并非总是如此,因为操作系统内核只运行在一个处理器上,但随着进程数量增加,其他任务便均匀地运行在每个处理器上。所以说,多处理器计算机的概念就是利用多个处理器来分担工作量。对于某些系统,在每个处理器上只能执行一项任务或一个进程,而在其他系统上,如Windows NT,每个处理器上可运行数千个任务。基本上这便是多重处理——多个任务运行在一台具有单个(或多个)处理器的计算机上。最新的概念是多线程,也是今天最令人感兴趣的术语。在Windows 95/98/NT/2000下的进程就是一个完整的程序;尽管有些时候进程不能够独立地运行,通常情况下它的确是一个应用程序。它能够拥有自己的内存空间、上下文,并独立存在。较之进程,线程(thread)是更为简单的程序实体。线程由进程创建,彼此间各不相同,结构简单并运行在创建它们所在的进程的地址空间内。线程的美妙之处在于它们能获得尽量多的处理器时间,并存在于创建它们的父进程的地址空间内。这意味着与线程的通信非常简单。本质上,线程恰是游戏程序员所需要的:一个执行线程并行地和其他的主程序任务一起工作,并可以访问程序中的变量。既然带有“multi-”前缀,因此你有必要搞清楚几个概念。首先,Windows 95、98、NT和2000都是多任务/抢先式操作系统。这表明任何任务、进程或线程都不能完全控制计算机。每一项任务、进程或线程在某种程度上都可被打断或被阻塞,而允许下一个执行线程开始运行。这与Windows 3.1完全不同——在Windows 3.1不是抢先式的。如果在每个循环中没有调用GetMessage(...),其他进程就不工作。而在Windows 95/98/NT/2000下,你可以设置一个无限FOR循环,而操作系统依然能使其他任务照常运行。而在Windows 95/98/NT/2000下,每一个进程或线程都有一个优先级,这个优先级决定了每个进程或线程在被打断之前的运行时间。所以,如果有10个相同的优先级进程,那么它们的运行时间相同或以循环的方式被处理。可是如果有一个线程具有内核级的优先级,该线程在每个循环中将获得更多的运行时间,如图11-16所示。图11-16:具有相等或不等优先级的轮转线程执行过程
最后,问题出现了:Windows 95/98/NT/2000的多线程间有什么区别?它们之间当然有一些区别。但符合Windows 95操作系统模型的程序大多可安全地运行在其他所有平台上。这是最基础的操作系统。尽管98和NT的稳定性更好一些,但在本节里我将仍然使用Windows 95机器来运行大部分的程序实例。