C++:多线程类库的设计与实现(一)

原文地址:http://yuyunwu.blog.sohu.com/63599338.html

引言

很多书都会告诉你那些概念是什么,然而只有很少的书会告诉你具体该怎么做。对于很多人来说,包括我,有时候掌握“该怎么做”要比了解“那是什么”要难得多。一方面,名词解释很少会出错,而且做起来很轻松,而要具体执行的话就立刻涉及到价值观和方法论的问题,这些都比较难于统一,容易引起异议。另一方面,就我个人经验而言,很多人只会解释“那是什么”,而根本不懂“该怎么做”。

 

所以,我们打算逆流而上,基本上不去说“那是什么”,除非有相当的必要。中心内容是着手“该怎么做”。

 

这个实践系列可以说是笔者积累的一些心得,当然,不可避免的要涉及到个人的价值观和方法论问题,不可避免的会产生异议。不过那又怎样呢,难道这个世界就不允许有异议吗。实际上,我个人并不排斥异议,相反的,我倒认为没有异议的氛围要么是可怕的,要么是病态的。

 

目标:用C++设计一个简单、实用、便于移植的线程类

 

先说第一条,简单,这里指模型简单,机制简单。

 

我们都知道线程是现代操作系统的基本概念之一,当然定义有很多种了,我们这里随便列一个:

(A thread is) A sequence of instructions which may execute in parallel with other threads.

 

这个定义是从Wiki上拷过来的,中文直译就是:(线程)是可以和其他线程并行执行的指令序列。这个定义是递归的,一般来说递归定义用来定义比较基本的概念,因为很难再往下分割了。

 

为了明确起见,我们再为上面的定义加一些限制,让它成为下面的样子:

 

1.线程是若干计算机指令序列的集合;

2.线程可以和其他线程并行执行;

3.属于同一个进程的若干个线程可以共享地址空间。

 

3条又带出另一个概念“进程”,这里就不再解释了。

 

很多操作系统中有所谓线程的同步通信和异步通信机制。我们只使用同步通信机制。这么做有两个好处,一是可以使我们的线程模型尽量简单,二是可以回避操作系统相关性,因为同步机制比较简单,大多数操作系统的实现相互都很类似,而异步通信机制差别就很大了。

 

我们再来说实用。

这里的实用是指实用主义,亦即为了减少成本(编码量)、提高效益(开发速度)而舍弃一些“本来应该有”的特性。比如说,我们不打算设计多层次的类,也不打算设计抽象类,而只打算设计一个可以简单使用的线程类。相反的,很多线程库,包括ZThread,将线程模型抽象分化,封装到多个层次的类里面。我们不是说这样的方针不好,这里只是想强调我们的方针是实用主义。

 

最后一条是关于移植性。

我们希望这个线程类可以不加修改就应用于Windows 32位系统和支持Posix Thread线程的Linux/Unix系统。

 

其他。

接下来我们来看看开发环境。我们要考虑同时支持Win32Linux系统。Windows上使用Microsoft ®Visual C++ 2005 Express,因这个软件包具有免费的许可协议,不需要花钱。Linux上使用g++(gcc)3.4.4,更高的版本应该也没有问题,使用这个版本是为了和某些cygwin版本兼容。当然,GNU流都是免费的。


背景:C++与多线程 

这个系列的主要内容是介绍怎样用C++语言设计与实现一个多线程类库。尽管多线程在现代主流操作系统中早已不是什么新鲜概念,多线程设计与开发也已经成为软件开发的流行模式,但是目前为止,C++语言规范本身并没有明确支持多线程程序设计。根据目前最新的C++语言标准《ISO/IEC 14882:2003 Programming Language C++》,通篇只有一个地方出现"thread"这个字眼:

When an exception is thrown, control is transferred to the nearest handler with a matching type (15.3); “nearest” means the handler for which the compound-statement, ctor-initializer, or function-body following the try keyword was most recently entered by the thread of control and not yet exited.

(笔者译文:

当一个异常被抛出时,(程序)控制被转交到最近的具有匹配类型的异常控制块。“最近”是指距离关键字try最近的并且与该控制同属一个尚未退出的线程的,一个复合代码断,或者构造函数的初始化符(即构造函数的成员初始化列表),或者一个函数体。


这是标准中唯一一次提到线程这个概念,意思大致是说C++异常控制是线程单位分开的。可见C++委员会并非是没有意识到线程概念的存在,而只是有意回避它。因为C++是一个标准的编程语言,独立于各种操作系统平台。线程是与操作系统具体实现密切相关的事物,C++语言中本身去支持线程是不合适的。只是在异常处理的定义中实在绕不开线程这个概念,才不得已而为之,即便如此也只是轻描淡写一笔带过。

而作为目前C++标准的一部分的C++标准类库STL也没有支持多线程。实际上STL的容器与算法模板都是多线程非安全的,用户需要自己编写多线程同步代码。

为什么C++不能象Java那样提供一个标准的多线程类库呢?笔者认为最主要是C++和Java的运行机制不同。C++是纯“官方”的ISO/IEC委员会这样的效率低下的机构所把持,当然笔者没有贬低ISO委员会的工作的意义,相反笔者认为这个工作意义简直太重大了,以至于ISO/IEC委员会很难把它做的尽善尽美。比如STL这种优秀的类库当年差点都被委员会给枪毙了,多线程标准类库的出现还不知道要等到猴年马月。而Java是由Sun公司主持开发,有其重大的商业战略意义,所以很多新技术一问世就很快被Java所吸收,二者的命运差别真是体制决定论的一个好例子。


开发C++多线程类库的工作已经由很多人在做了,其中比较有名的是 ZThread boost类库 的Thead。目前把boost库的Thread类纳入C++标准的呼声看似比较高。

那么笔者还干什么呢?哈哈,笔者主要认为这两个库结构都太麻烦了,而且要带一堆看似不相干的其他文件,用起来麻烦。另外白手起家开发一个多线程类库也不失作为程序员的一件乐事,还能学习不少知识,温故而知新,学习之道也。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值