11.2 C++中的并发

在C++标准委员会创建最初的C++标准时,并发机制被明确排除在外,因为C没有并发,也还因为有许多极具竞争力的近似方法可以实现并发处理。似乎有太多的限制迫使程序员只能用这些方法中的一个。

然而,那些可供选择的方法,结果被证明是错的。为使用并发,就要找到和学习一个库,这就涉及库的特性和某个特定(软件)供应商的产品在工作时是否可靠的问题。另外,没有人能够保证这样的库能运行在不同的编译器上或者跨不同的平台运行。并且,既然并发不是标准语言的一部分,所以要找到懂得并发编程的C++程序员也会更困难。

另一种有影响的Java语言,把并发包含在核心语言中。尽管多线程处理仍然是复杂的,但Java程序员在学习的起始就注意学习多线程并从一开始就使用它。

C++标准委员会正在考虑把支持并发处理的功能加入到下一代C++语言中,但是在这一次正在编写的新版本中,还不清楚加入并发处理的库看起来像什么样子。因此,作者决定把ZThread库作为这一章的基础。首选该设计的原因,因为它是源代码开放的,并且可以免费在

http://zthread. sourceforge.net网站上获取。ZThread的作者,IBM的Eric Crahen,为本章提供了很多有用的工具。[1]

本章仅使用ZThread库的一个子集,以传达线程处理的基本思想。值得注意的是,ZThread库还包含重要的比这里所展现的更复杂的对线程的支持,应该深入研究这个库才能更进一步地、完全理解它的性能。

安装ZThread

请注意,ZThread库是一个独立的项目,本教材的作者并不支持它;只是在本章中使用这个库,不能提供关于安装发行(installation issue)的技术支持。浏览ZThread的网站可以得到安装支持以及勘误报告。

ZThread库以源代码形式发布。从ZThread网站将其下载后(版本2.3或更高的版本),必须首先编译这个库,然后装配到项目中来使用这个库。

对大多UNIX风格的操作系统(Linux、SunOS、Cygwin等等),编译ZThread首选的方法是使用装配脚本(configure script)。文件解包(使用tar)后,仅执行:

11.2 C++中的并发 - 图1

从ZThread档案文件的主目录开始编译,在/usr/local目录安装库的一份拷贝。使用这个脚本时可以自定义一些选项,包括文件的位置。若要了解详细内容,可以使用下面这个命令:

11.2 C++中的并发 - 图2

ZThread的代码也被组织成能对其他平台和编译器(比如Borland、Microsoft和Metrowerks)进行简化编译的形式。为了完成这个工作,创建一个新项目,把ZThread档案文件的src目录中的所有.cxx文件加入到文件列表中,然后进行编译。同时也要确保把档案文件的include目录包含在该项目的头文件搜索路径(header search path)下。具体的细节根据编译器的不同而有所不同,所以需要比较熟悉这些工具包后才能够使用这个选项。

一旦编译成功,下一步就是创建一个使用这个重新编译好的库的项目。首先,让编译器知道头文件放置的位置,以便程序中的#include语句能够正常工作。典型地,要将如下选项加入到工程:

11.2 C++中的并发 - 图3

如果使用装配脚本,可以选择任意安装路径作为前缀的路径(默认的情况是在/usr/local)。如果使用build目录中的某个项目文件,只需将ZThread档案文件的主目录设置为安装路径。

接下来,需要在项目中加入一个选项,这会使连接器(linker)知道到哪里去寻找库。如果使用装配脚本,如下所示:

11.2 C++中的并发 - 图4

如果使用一个已提供的项目文件,那么应该这样做:

11.2 C++中的并发 - 图5

再说一遍,如果使用装配脚本,可以选择任意安装路径作为前缀的路径。如果使用已提供的项目文件,路径就是ZThread档案文件的主目录。

注意,如果使用Linux或使用Windows下的Cygwin(www.cygwin.com),则不需要修改包含路径或库文件路径;安装进程及默认选项会做好全部工作。

在Linux下,也许需要把下面的东西添加到.bashrc文件中,以便让运行时系统(runtimesystem)能够在执行本章中的程序时找到共享库文件LibZThread-x.x.so.O:

11.2 C++中的并发 - 图6

(假设使用的是默认安装进程和位于路径/user/local/lib下的共享库;否则,把路径改成用户所使用的位置。)

[1]本章的大部分开始于《Thinking in Java,3 third edition》(Prentice Hall 2003)的“并发”一章,而在处理上有非常显著的改变。