[置頂]

書單: 安迪葛洛夫:Only paranoid survives.

Jan 17, 2008

侯捷網頁 - Win32 多绪程式设计

--------------------------------------------------------------------------------

四刷 3600 册
《Win32 多绪程式设计》
Multithreaded Applications in Win32
侯捷 译


繁体版 勘误


--------------------------------------------------------------------------------

【基本资料】

书名:Win32 多绪程式设计
出版: 峰,1997.08
ISBN:957-566-075-7
页数: 16 章,453 页
定价:NT$ 640.0

原着:Multithreaded Applications in Win32
原着作者:Jim Beveridge & Robert Wiener
原着出版:Addison Wesley, 1997
原着ISBN:0-201-44234-5
原着定价:US$ 39.95


【译序】

叙绪之序 絮絮如絮

(译 序)

作者在本书第一章的第一句话让我沉思良久。他说:『电脑工业界每有新的技术问世,人们总是不遗馀力地去担忧「它是不是够重要」。公司行号虎视眈眈地注意其竞争对手,直到对方采用并宣扬这技术有多麽重要,才开始急急赶上。不论这技术是不是真的很重要,每一个人都想尽办法让终端用户感觉「真的很重要」。终端用户终於真的觉得需要它了
-- 即使他们完全不了解那是什麽东东。』

执行绪(thread)大约就是其一吧。OS/2 和 Windows NT 以及 Windows 95
上市时,一再强调其强制性多工(preemptive
multitasking)的多执行绪(multithreaded)环境。霎时间线头到处飞舞,电脑科学里十分高深的名词也在街巷里弄之间传播了开来,颇有点
"Nerual Fuzzy" 洗衣机的味道。

这倒也算好事。没有把「执行绪」搞清楚是怎麽回事,对终端用户而言或许还没有关系,但是对搞技术的人可就不妙。执行绪绝对可以提升程式的执行效率?所以尽量多产生执行绪来帮助程式工作?任何种类的程式都可以获得多执行绪的好处?错!错!错!这种似是而非的观念可能把你的程式带往一种更坏(而不是更好)的境界。

执行绪并不是新东西,只是它藉着 Windows
的庞大装机量,第一次广泛进入个人电脑的世界,带给我们巨大的刺激。执行绪并不难产生,要它们分工可以,但要它们合作就得相当花心思了。执行绪不一定带来好处,运用不好它会在执行效率上惩罚你。

执行绪是 Win32 作业系统和 Win32
程式设计上不可或缺的重要环节,每一本重量级的书籍都不会忽略这个题目(请叁考附录B)。但是这些书多半仅以一章(有的甚至是一节)来介绍这个题目。不够,真的不够。我们缺乏一本兼具理论并重实际的多绪程式设计书籍。这本书很早就在
Addison Welsey 的书目上引起我的注意。它的内容,的确兼具理论并重实际。它的轻薄短小,也在大部头书当道的今天,让做为读者的我心情轻松不少。不过,执行绪这个主题是不可能让我们轻松的,同步控制、执行绪通讯、资料一致性...,读这本书还是请你安装一下自己的精神。

对於这本翻译书,我有以下几点说明:

1. 译本中的范例程式码直接取自书附碟片中的实例。如果与原书内容稍有出入,那是因为作者最後又做的一点点小变动。我想,以碟片内容为主会比较实际。通常在差异之处我会以译注的方式告诉你。

2. 这本译作保留了相当多的原文技术名词。这是一种尝试,主要是考虑到这本书的潜在读者。如果不讲原文名词,可能他们反而要倒译回去,那麽本书就适得其反了。许多地方我不厌其烦地在中文名词後面加上原文名词,为的也是同样的原因。

「执行绪」这项技术非常重要,当支援多处理器(CPU)的作业系统逐渐普及,当多处理器的 PC
也逐渐普及,我相信「执行绪」是每一位技术人员都必须拥有的技术。即使是现在,「执行绪」能够提高程式的反应度,也是高级技术人员应该追求的技术。

侯俊杰 1997.01.30 于新竹


【导读】

前言

1992 年,我叁加了第二届的 Microsoft Professional Developers Conference,当时 Win32
首次对大量观众展示。这是一个重大的事件,其中有许多蛊魅的新技术第一次亮相。观众不断地对展示的东西喝采。当我看到这些新技术,我身上 Unix
的那一部份说『时候到了』,而 Windows 3.1 的那一部份则是高呼『哈利路亚』。

五年过去了,好几版 Windows NT 问世了。我愈是深入此书,愈是了解1992
年的那场盛宴之中我的了解多麽贫乏。我听过许多「睿智」的话,像是「为 MDI
程式的每一个视窗准备一个执行绪」之类,事实上根本错误。有些技术(诸如 overlapped I/O)很明显地被曲解。

当我钻研此书,我发现许多其他书籍和文章从头到尾描述了各式各样的 Win32
函式,却很少着墨在如何使用它们,或如何搭配其他函式使用。某些函式,例如 MsgWaitForMultipleObjects(),是
Win32 程式的运转中心,却几乎没有任何范例程式正确使用过它。在我所发现的文件给了我太多的挫败之後,我决定尽可能以实务导向的方式完成此书,如此一来你就能看到那些
Win32 函式一起合作的情景。

这本书的读者群很广,Win16 和 Unix 上的程式开发者欲移转到 Win32,或是有经验的 Win32
程式开发者,都是我的对象。你会发现一些不曾看过的问答,像是「为什麽 _beginthreadex()
真的很重要」等等。程式范例从基本层面到同步机制,到多绪 COM 和 ISAPI 应用程式,都有。

这是一本可以让你上手实验「Win32
执行绪」的书。我描述了基础观念,如果你需要更理论性的知识,你得多看点其他资料。执行绪的大部份问题都已经被像 Dijkstra 和
Courtois 那样的人在 25 年前就解决掉了。他们的论文直到今天还适用。

如果你对那些只挑软柿子吃而故意忽略困难部份的书籍感到绝望,我希望本书能够让你绝地逢生。某些章节是经过了长时间的实验、多篇相关文章(来自杂志、期刊、Microsoft
Knowledge Base)的阅读、众多原始码的剖析之後,萃炼而得。像「执行绪与 C runtime 函式库以及 MFC
的关系」这种主题,我保证你会从中获得许多闪亮宝石。

许多程式员对於执行绪是既期待又怕受伤害。Unix 的人嘲笑它,因为行程(process)看起来就已经不错了。Win16 的人也嘲笑它,因为
PeekMessage() 也运作得很好嘛!我写这本书时首要认识的一个关键问题就是:如果有任何一个人在乎所谓的执行绪,他为的是什麽?

如果你开发的是伺服器(server)产品,你就应该对执行绪深深在乎,因为 I/O completion ports 使用它。I/O
completion ports 是唯一能够搭配 Win32 sockets 或 named pipes 完成高效率 I/O
的方法。请你「跑」到第6章看个明白(用走的太慢了)。

如果你开发的是 Web 产品,IIS(Internet Information Server)的扩充软体也是靠多执行绪 DLLs
完成。这种技术的背景观念散布於整本书,而第16章告诉你如何施行那些观念。

本书第一篇的程式是以 C 完成,C++ 的份量很少。从第二篇开始我们就往 C++ 移动了。一如我在第9章所说,C++
是大势所趋,不论你是否使用 MFC。如果你的 C++ 根基不稳,我希望你特别注意一下第9章。

谁应该读这本书

凡是 C/C++ 程式开发人员,并有 Windows 程式设计经验(不论是 Win16
或Win32),企图对执行绪、核心物件、overlapped I/O in Win32
获得更坚实之认识者,本书就是针对你们而写的。本书谈的是 API 函式的使用、你会遭遇的问题、以及 Windows 架构对其用途的影响。

读过本书之後,你将有能力分析哪里是执行绪可以发挥效用的地方,哪里是你应该闪躲它们的地方。几乎整本书的重点都放在产生真正可用的程式。神秘手法以及不安全的设计已经被我排除了。

Unix 程式员将会发现,Win32 和 Unix 之间有着基础观念上的差异。

本书架构

本书的第一篇,「上路吧,执行绪」,为你建立必要的基础,包括执行绪的启动和结束、核心物件、激发和未激发状态的意义、同步机制及其用途。有经验的
Win32 程式员或许可以跳过这一部份。不过第6章所讨论的主题(诸如 I/O completion
ports),是非常重要的题目,而且总的来说,其文件非常贫乏。

本书的第二篇,「多绪程式设计的工具与策略」,介绍 C runtime 函式库和 MFC 对执行绪的支援、如何在 USER 和 GDI
的限制之下施行多执行绪、如何产生一个 DLL、如何对多绪程式除错。这一部份的许多资讯来自於我们的研究和实作经验。

本书的第三篇,「真实世界中的多绪应用程式」,谈论如何组织一个程式,使它有效支援多执行绪。本篇示范两个真实世界中的应用软体,第一个是个
freethreaded OLE automation server,第二个是 ISAPI 程式,是个 IIS(Internet
Information Server)扩充软体,示范如何和 JET 资料库交谈。

关於范例程式

整本书中我用了许多文字模式程式来示范观念。有些人不喜欢这种选择,但我相信一个 50~100
行的程式绝对比一个有着讯息回路、资源档案、视窗函式...并且超过 750 行的 Windows
程式更能够集中读者的目光。读这本书不会看到太多与使用者介面相关的东西。我相信本书的范例程式以其目前的形态对你会比较有帮助。

面对这些范例程式,我使用多方的错误检验。虽然这些检验导至程式码看起来有些杂乱,但是错误检验对於生产一个真正的应用软体很重要,对於一本书也很重要。

相关阅读

有两样东西是任何时候你尝试写任何 Win32 程式时应该要准备的。第一样东西是 Microsoft Developer
Network。其光碟片内含不可置信的巨量技术资料,包括 Microsoft Knowledge Base、编译器和 Win32
的完整手册、以及 Microsoft Systems Journal。

第二样东西是 Jeffrey Richter 的一本卓越书籍:Advanced Windows NT : The Developers
Guide to the Win32 API for Windows NT 3.5 and Windows NT(Microsoft
Press,1995)。虽然其中遗漏了某些 NT 3.51 的新东西,但其他方面非常有价值。

译注:Jeffrey 的书已出至第3版,名为 Advanced Windows Third Edition. 它的小标题写着:for
Windows 95 & Windows NT 4.0。


【目录】

常见问答集(Frequently Asked Questions)
前言

第一篇 上路吧,执行绪

第1章 为什麽要「千头万绪」
一条曲折的路
与执行绪共枕
为什麽终端用户也需要多绪多工
Win32 基础
Context Switching
Race Conditions(竞速状态)
Atomic Operations(不可分割的动作)
执行绪之间如何通讯
好消息与坏消息

第2章 执行绪的第一次接触
产生一个执行绪
使用多个执行绪的结果
核心物件(Kernel Objects)
执行绪结束码(Exit Code)
结束一个执行绪
错误处理
背景列印(Background Printing)
成功的秘诀

第3章 快跑与等待
看似闲暇却忙碌(Busy Waiting)
效能监视器(Performance Monitor)
等待一个执行绪的结束
叮咚:被激发的物件(Signaled Objects)
等待多个物件
在一个 GUI 程式中等待
提要

第4章 同步控制(Synchronization)
Critical Sections(关键区域、临界区域)
死结(Deadlock)
哲学家吃饭问题(The Dining Philosophers)
互斥器(Mutexes)
号志(Semaphores)
事件(Event Objects)
从 Worker 执行绪中显示输出
Interlocked Variables
提要:关於同步机制(Synchronization Mechanisms)

第5章 不要让执行绪成为脱 野马
乾净地中止一个执行绪
执行绪优先权(Thread Priority)
初始化一个执行绪
提要

第6章 Overlapped I/O,在你身後变戏法
Win32 档案操作函式
被激发的 File Handles
被激发的 Event Objects
非同步程序呼叫(Asynchronous Procedure Calls,APCs)
对档案做 Overlapped I/O 的缺点
I/O Completion Ports
对 Sockets 使用 Overlapped I/O
提要

第二篇 多绪程式设计的工具与手法

第7章 资料一致性(Data Consistency)
认识 volatile 关键字
Referential Integrity
The Readers/Writers Lock
我需要锁定吗?
Lock Granularity
提要

第8章 使用 C Run-time Library
什麽是 C Runtime Library 多绪版本
选择一个多绪版本的 C Runtime Library
以 C Runtime Library 启动执行绪
哪一个好:CreateThread() 抑或 _beginthreadex()?
避免 stdio.h
一个安全的多绪程式
结束行程(Process)
为什麽你应该避免 _beginthread()
提要

第9章 使用 C++
处理有问题的 _beginthreadex() 函式原型
以一个物件启动一个执行绪
建立比较安全的 Critical Sections
建立比较安全的 Locks
建立可交替授受(Interchangeable)的 locks
异常情况(Exceptions)的处理
提要

第10章 MFC 中的执行绪
在 MFC 中启动一个 Worder 执行绪
安全地使用 AfxBeginThread() 的传回值
在 MFC 中启动一个 UI 执行绪(User Interface Thread)
和 MFC 物件共处
MFC 的同步控制
MFC 对於 MsgWaitForMultipleObjects() 的支援
提要

第11章 GDI 与视窗管理
执行绪的讯息伫列
讯息如何周游列国
GUI 效率问题
以 Worker 执行绪完成多绪版 MDI 程式
多个上层视窗(Top Level Windows)如何是好?
执行绪之间的通讯
NT 的影子执行绪(shadow thread)
关於 "Cancel" 对话盒
锁住 GDI 物件
提要

第12章 除错
使用 Windows NT
有计划地对付错误
Bench Testing
执行绪对话窗
运转记录(Logging)
Memory Trails
硬体除错暂存器
科学方法
提要

第13章 行程之间的通讯(Interprocess Communication)
以讯息伫列权充资料转运中心
使用共享记忆体(Shared Memory)
使用指标指向共享记忆体(Shared Memory)
较高层次的行程通讯(IPC)
提要

第14章 建造 DLLs
DLL 的通告讯息(Notifications)
通告讯息(Notifications)的问题
DLL 进入点的依序执行(Serialization)特性
MFC 中的 DLL 通告讯息(Notifications)
喂食给 Worker 执行绪
执行绪区域储存空间(Thread Local Storage,TLS)
_declspec(thread)
资料的一致性
提要

第三篇 真实世界中的多绪应用程式

第15章 计划一个应用程式
多执行绪的理由
要执行绪还是要行程?
多绪程式的架构
评估既有程式码的适用性
对 ODBC 做计划
他人开发的函式库(Third-Party Libraries)
提要

第16章 ISAPI
Web 伺服器及其工作原理
ISAPI
IS2ODBC 范例程式
提要

第17章 OLE,ActiveX,COM
COM 的执行绪模型(COM Threading Models)
AUTOINCR 范例程式
提要

附录A MTVERIFY 巨集
附录B 更多的资讯


--------------------------------------------------------------------------------

No comments: