微软64位windows操作系统常规编程简介
作者:开发合作部 来源:微软(中国)有限公司 添加时间:2006-5-26 12:55:20线程:如何有效地使用它们
在线程间分割您的工作可以简化代码,在多处理器系统上可以使您的代码更有效,但是如果您不知道自己在做什么的话,还会降低性能和可伸缩性。例如,如果应用程序中的所有线程都需要获得相同的全局关键部分,那么对该关键部分的争用可能会使您的线程花费其大部分休眠时间。它还可能导致发生过多的上下文转换,进而可能会引起应用程序占用系统内核中相当比例的处理时间,甚至根本没有运行您的代码。如果在多处理器的系统上,这些问题会尤其糟糕,您额外的处理器可能会结束当前闲置,等待访问共享数据。
要使用的线程的理想数量等于系统中处理器的数量。如果您的线程相互独立并受到处理器的限制,那么它们应该能够每次都消耗掉其整个时间片。如果您具有可能执行阻止操作的线程,那么您可能希望增加线程的数量,以便当一个线程休眠时,另一个线程可以取代其位置。您将要确定线程阻塞的位置及频率。意识到这一点后,您就可以知道应该运行的线程数量。您始终要为每个处理器准备好一个线程。否则,您就浪费了处理能力。当然,这些仅仅是指导原则,并且确定应用程序是否以尽可能高的效率运行的唯一方法就是对其进行分析和测试。
异步 I/O:不会阻塞等待数据
基于 NT 内核的 Windows 系统支持异步 I/O,又称重叠的 I/O。大多数形式的 I/O 都可以异步完成。这包括文件 I/O 和网络 I/O。对于文件 I/O,您可以使用 ReadFile/WriteFile API。当读/写时,通过借助 FILE_FLAG_OVERLAPPED 标记打开文件并指定 OVERLAPPED 结构,您将使系统在 I/O 完成时通知您。这使您可以在等待的过程中完成其他工作。对于使用 Windows Socket (WinSock) 的网络 I/O,您可以使用 WSASocket 创建套接字,并指定 WSA_FLAG_OVERLAPPED 标记,然后当调用 WSARecv/WSASend API 时,您可以指定一个 OVERLAPPED 结构或一个回调函数。当您编写网络服务器时,异步 I/O 尤为有效。您可以将多个接收请求“排入队列”,然后去休息,等待其中一个完成。当一个完成时,就会处理传入的数据,然后将另一个接收“排入队列”。这比使用 select API 来轮询数据好得多,并且它可以更有效地使用系统资源。
等待异步 I/O 请求完成有几种选项:
调用 GetOverlappedResult API
在发出异步 I/O 请求后,您可以使用 GetOverlappedResult API 来轮询请求的状态,或者仅仅等待请求的完成。当请求完成时,GetOverlappedResult 将返回请求过程所传输的字节数。
使用 HasOverlappedIoCompleted 宏
您可以使用 HasOverlappedIoCompleted 宏来有效地进行轮询与 OVERLAPPED 结构相关联的请求是否已经完成。请求完成后,您就可以使用 GetOverlappedResult API 来获得有关请求的更多信息(例如传输的字节数)。