邓学明
(四川托普信息技术职业学院 计算机系软件研究所)
1. 前言
就在几年前,用多线程执行程序还是一件非比寻常的事。然而今天互联网应用服务程序普遍使用多线程来提高与多客户链接时的效率;为了达到最大的吞吐量,事务服务器在单独的线程上运行服务程序;GUI应用程序将那些费时,复杂的处理以线程的形式单独运行,以此来保证用户界面能够及时响应用户的操作。这样使用多线程的例子还有很多。
但是C++标准并没有涉及到多线程,这让程序员们开始怀疑是否能够写出多线程的C++程序。尽管无法写出符合标准的多线程程序,但是程序员们还是会使用支持多线程的操作系统提供的多线程库来写出多线程C++程序。但是这样做至少有两个问题:这些库大部分都是用C语言完成的,如果在C++程序中要使用这些库就必须十分小心;还有,每一个操作系统都有自己的一套支持多线程的类库。因此,这样写出来得代码是没有标准可循的,也不是到处都适用的(non-portable)。Boost线程库就是为了解决所有这些问题而设计的。
Boost是由C++标准委员会类库工作组成员发起,该工作组是致力于为C++开发新的类库的组织。现在它已经有近2000名成员。许多库都可以在Boost源码的发布版本中找到。为了确保这些类库是线程安全的(thread-safe),Boost线程库被创建了。
许多C++专家都投身于Boost线程库的开发中。所有接口的设计都是从0开始的,并不是C线程API的简单封装。许多C++特性(比如构造函数和析构函数,函数对象(function object)和模板)都被使用在其中以使接口更加灵活。现在的版本可以在POSIX,Win32和Macintosh Carbon平台下工作。
本文运用利用Windows平台的VC7开发工具,介绍了如何使用Boost库中的Thread 库实现多线程的应用程序。
2. Boost
2.1. C++ Boost库简介
boost是一个准标准库,相当于STL的延续和扩充,它的设计理念和STL比较接近,都是利用泛型让复用达到最大化。不过对比STL,boost更加实用。STL集中在算法部分,而boost包含了不少工具类,可以完成比较具体的工作。
boost主要包含一下几个大类:字符串及文本处理、容器、迭代子(Iterator)、算法、函数对象和高阶编程、泛型编程、模板元编程、预处理元编程、并发编程、数学相关、纠错和测试、数据结构、输入/输出、跨语言支持、内存相关、语法分析、杂项。有一些库是跨类别包含的,就是既属于这个类别又属于那个类别。
2.2. 编译安装Thread 库
在Boost中绝大多数库无需要编译可以直接使用,但仍有一些由于平台相关性的原因需要Build相应的lib或dll文件,Thread便是其中之一。
由于Boost使用jam工具进行编译安装,所以第一步应先编译jam工具,在开始编译前应先安装好VC7开发环境,以下以$BOOSTDIR表示boost的存放目录。
到$BOOSTDIR\tools\build\jam_src下执行build.bat对jam进行编译,编译结果将存放在$BOOSTDIR\ tools\build\jam_src\bin.ntx86下。
将$BOOSTDIR\ tools\build\jam_src\bin.ntx86加入PATH或复制bjam.exe到Widnows目录,下面我们利用jam来编译安装Thread库。
到$BOOSTDIR\libs\thread\build下执行
bjam -sTOOLS=vc-7_1 -sBUILD=debug和
bjam -sTOOLS=vc-7_1 -sBUILD=release进行编译,编译结果将存放在$BOOSTDIR\libs\thread\build\bin-stage下。
3. 应用Boost Thread
3.1. 准备工作
在VC7中新建一个Win32控制台项目,并将运行时库设置为多线程DLL,然后在设置附加库目录处加上$BOOSTDIR\libs\thread\build\bin-stage
3.2. 创建线程
就像std::fstream类代表一个文件一样,boost::thread类代表一个可执行的线程。缺省构造函数创建一个代表当前执行线程的实例。一个重载的构造函数以一个不需任何参数的函数对象作为参数,并且没有返回值。这个构造函数创建一个新的可执行线程,它调用了那个函数对象。
最初,大家认为传统C创建线程的方法似乎比这样的设计更有用,因为C创建线程的时候会传入一个void*指针,通过这种方法就可以传入数据。然而,由于 Boost线程库是使用函数对象来代替函数指针,那么函数对象本身就可以携带线程所需的数据。因此这种方法更具灵活性,也是类型安全(type-safe) 的。当和Boost.Bind这样的功能库一起使用时,这样的方法就可以让你传递任意数量的数据给新建的线程。
3.3. 代码实现
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
void hello(const std::string &speekst)
{
std::cout <<speekst<< std::endl;
}
int main(int argc, char* argv[])
{
int iEnd;
boost::thread thrd(boost::bind(hello,std::string("a Thread")));
boost::thread other(boost::bind(hello,std::string("another Thread")));
thrd.join();
other.join();
std::cin>>iEnd;
return 0;
}
3.4. 运行结果
运行程序后,屏幕上将输出:
a Thread
another Thread
3.5. 代码分析
首先,创建了两个线程
boost::thread thrd(boost::bind(hello,std::string("a Thread")));
boost::thread other(boost::bind(hello,std::string("another Thread")));
创建线程时使用了重载的构造函数。由于重载的构造函数只能接受不需任何参数的函数对象作为参数,但hello函数对象有一个const std::string &类型的参数,所以将Boost.Bind作为参数传入构造函数,并且使用Boost.Bind还可以简化创建线程携带数据,避免使用函数对象。
然后,执行线程对像的jion成员函数来等待线程执行完毕
thrd.join();
other.join();
join并不是启动线程,只是等待线程执行结束。本例中线程构造完成后立即执行。
4. Boost Thread的未来
Boost线程库正在计划加入一些新特性。其中包括boost::read_write_mutex,它可以让多个线程同时从共享区中读取数据,但是一次只可能有一个线程向共享区写入数据;boost::thread_barrier,它使得一组线程处于等待状态,直到所有线程都进入了屏障区; boost::thread_pool,它允许执行一些小的routine而不必每一次都要创建或是销毁一个线程。
Boost线程库已经作为标准中的类库技术报告中的附件提交给C++标准委员会,它的出现也为下一版C++标准吹响了第一声号角。委员会成员对Boost 线程库的初稿给予了很高的评价,当然他们还会考虑其他的多线程库。他们对在C++标准中加入对多线程的支持非常感兴趣。从这一点上也可以看出,多线程在C ++中的前途一片光明。
5. 结束语
目前,由Boost线程库创建的线程对象功能还不是很强大。事实上它只能做两项操作。线程对象可以方便使用==和!=进行比较来确定它们是否是代表同一个线程;你还可以调用boost::thread::join来等待线程执行完毕。其他一些线程库可以让你对线程做一些其他操作(比如设置优先级,甚至是取消线程)。然而,由于要在普遍适用(portable)的接口中加入这些操作不是简单的事,目前仍在讨论如何将这些操组加入到Boost线程库中。
本例仅仅示范了如何使用Boost库来编写多线程的应用,在实际的软件开发中可根据实际情况在此示例上加以扩充,以达到自己的需求。
posted on 2007-04-24 09:58
清源游民 阅读(1991)
评论(0) 编辑 收藏 引用