2024年5月25日发(作者:)

多线程编程

::

用线程提高效率

(pthreads

指南

)

序言

如今绝大多数的代码都是线性执行的

.

我们说到线性和线性化的指的是什么呢

?

简单说

,

就是代码是指令

一条接着一条在单片机里执行的

,

无视了许多为程序提供的可能可用的资源

.

如果程序执行了一个阻塞调用

的话

,

程序的总体效率会大大降低

.

为什么绝大多数程序都是线性的

?

一个可能的原因是程序员可用的机器中单处理器系统占据了相对的

优势

.

绝大多数情况下

,

在一台单处理器的机器上让一个程序多线程化不会获得足够的好处

,

也不值得为之花

去大量的时间和劳力

.

另外一个可能是绝大多数人都以线性的方式思考问题

.

并行思考不是件天生就会的事

情也一点不简单

.

但是

,

时代变了

,

大量关于多线程的论文发表出来

.

有人在鼓吹多线程的使用

,

也有人持反对意见

.

随着对

称多进程机器越来越受欢迎

,

编写多线程代码也成为一项值得学习的技能

.

我们会在一点理论介绍后进入多线程的世界

.

我们会先检验线程同步原理

,

然后给出如何使用

POSIX

pthreads

的指南

.

最后

,

我们会以线程效率和一个多进程编程的概要结束本文

.

什么是线程?

Part I ::

定义

那不是你用来穿针眼的线吗?

是的

.

那它怎么和编程联系起来了?

把针想象成

CPU

(或轻量级线程)然后程序中的线程是针上的线。如果你有两个针却只有一根线,比

起把线剪成两段来使用两颗针而言,这样完成这项工作你需要花费更多的时间。把这个比方再扩展一下,

如果一颗针要缝一个钮扣(

I/O

阻塞),即使这项工作要耗去

4

小时

,

另外一颗针也能同时做别的有用的工

作。如果你只用一颗针

,

你会整整迟

4

小时!

既然我们已经在头脑中画出了缝针,让我们进一步联想到更具体的事情。一个线程是一个可以和别的

线程并行执行的指令序列

[]

。他们不是进程,而是可执行的轻量级线程。这似乎是一个递归定

义但它确实是有意义的。程序的线程并不是完整的进程,而是同时执行(或并行执行)的较小的进程部分。

因此我们使用了轻量级这个词。

Part II::

操作系统支持

你不能期待一个多线程的程序在一个不支持多线程的系统内核上运 行。所幸大多数操作系统都是支

持多线程的,依靠它们自身的线程库或者

POSIX pthreads

。简单列出一些,

Sun Solaris, FreeBSD, Linux,

AIX, HP-UX, IRIX,

以及

Windows NT

都支持多线程程序。但是每个操作系统都用了不同的技术来支持线程。

在谈及如何支持多线程前,我们先得熟悉一些词汇:

轻量级进程

(LWP)

可以看作是一个虚拟的中央处理单元,其中轻量级进程的数量通常多于

CPU

的数

量。线程库通过和轻量级进程的通信来控制线程。轻量级进程有时也指内核线程。

X-to-Y

模型

(X-to-Y model)——

轻量级进程到线程的映射关系。

争夺范围

(Contention Scope)

描述进程是如何争夺系统资源的

(

如进程调度

)

束缚线程

(Bound threads)

有全系统的争夺范围,换句话说,它们在整个系统上和别的进程争夺资源

(因此是由内核调度的)

无束缚线程

(Unbound threads)

的争夺范围在进程内,也就是说,它们由线程库安排到可用的的轻量级

进程上。

Solaris

使用多对多模型。所有的

CPU

可以对应到任何一个轻量级进程上去,后者也可以对应到任意

的线程。内核为轻量级进程调度

CPU

时间片。

Linux

使用一对一模型。每一条线程映射一个单独的轻量级进程。为什么在

Linux

中这种模式会比多对

多更受欢迎呢? 因为

Linux

的轻量级进程是真正的轻量级的,其构建花费远没有

Solaris

那么高昂。另一个

Linux

中让你选择将程序多线程化而不是多进程化的加分 点在于调度器

(scheduler(2.4))

对于和当前运行进

程在同一个线程簇的进程会给予一定的优先权。

此外,建立束缚还是非束缚线程能在很大程度上影响拟定多线程程序的效率。使用其中任何一种都没

有普遍的规则。每一种特定环境都要求完备的分析来决定选取哪种类型的线程来完成工作。

Part III::

其它名词

安全线程

(thread-safe)

指程序保护共享数据,很可能依靠互斥实现。

重入码

(reentrant code)

指一个程序能有多个正在同时执行的线程。

异步安全

(async-safe)

只一个函数在运行一条句柄的时候是能重入的

(

比如,能由其它句柄调用

)

同时性

(concurrency)

和并行性

(parallelism)——

它们是不一样的!并行性是同时性的一个子集。并行性

意味着代码的同时运行

(

在单处理器机器上这是不可能的

)

,而同时性意味着多个任务可以以任何顺序

执行,有可能是并行执行。

Part IV::

线程规范

是的,线程很厉害

......

对合适的作业而言!不要把时间浪费在编写一个不值得多线程化的多线程程序。

有时候基于事件编程是更好的方法,或者仅仅直接而简洁的线性代码就能完成任务。

哇,你要在这么简单的问题上浪费了一个小节?是的,在怎么选择合适的工具这点上再怎么强调也

不为过。

线程设计方案

既然已经有了些线程的基本知识,我们来讨论下如何正确的使用最适合手头工作的线程。