多线程概念
并发性和并行性
在单个处理器的多线程进程中,处理器可以在线程之间切换执行资源,从而执行并 发。
在共享内存的多处理器环境内的同一个多线程进程中,进程中的每个线程都可以在一 个
单独的处理器上并发运行,从而执行并行。如果进程中的线程数不超过处理器的数 目,
则线程的支持系统和操作环境可确保每个线程在不同的处理器上执行。例如,在 线程数
和处理器数目相同的矩阵乘法中,每个线程和每个处理器都会计算一行结果。
多线程结构一览
传统的UNIX已支持多线程的概念。每个进程都包含一个线程,因此对多个进程进行 编程即
是对多个线程进行编程。但是,进程同时也是一个地址空间,因此创建进程会 涉及到创建新
的地址空间。创建线程比创建新进程成本低,因为新创建的线程使用的是当前进程的地址空间。
相 对于在进程之间切换,在线程之间进行切换所需的时间更少,因为后者不包括地址空 间之
间的切换。在进程内部的线程间通信很简单,因为这些线程会共享所有内容,特别是地址空间。
所以,一个线程生成的数据可以立即用于其他所有线程。 在Solaris9和较早的Solaris发行版中,
支持多线程的接口是通过特定的子例程库实现 的。这些子例程库包括用于POSIX线程的libpthread
和用于Solaris线程的 libthread。多线程通过将内核级资源和用户级资源分离来提供灵活性。在
当前的发行 版中,对于这两组接口的多线程支持是由标准C库提供的。
用户级线程
线程是多线程编程中的主编程接口。线程仅在进程内部是可见的,进程内部的线程会 共享诸如地址空间、打开的文件等所有进程资源。
用户级线程状态
以下状态对于每个线程是唯一的。
■ 线程ID
■ 寄存器状态(包括PC和栈指针)
■ 栈
■ 信号掩码
■ 优先级
■ 线程专用存储
由于线程可共享进程指令和大多数进程数据,因此一个线程对共享数据进行的更改对 进程内其他线程是可见的。
一个线程需要与同一个进程内的其他线程交互时,该线程 可以在不涉及操作系统的情况下进行此操作
线程调度
POSIX标准指定了三种调度策略:先入先出策略(SCHED_FIFO)、循环策略(SCHED_RR)和 自定义策略(SCHED_OTHER)。
SCHED_FIFO是基于队列的调度程序,对于每个优先级都会 使用不同的队列。
SCHED_RR与FIFO相似,不同的是前者的每个线程都有一个执行时间 配额。
SCHED_FIFO和SCHED_RR是对POSIX Realtime的扩展。SCHED_OTHER是缺省的调度策略。
线程取消
一个线程可以请求终止同一个进程中的其他任何线程。目标线程(要取消的线程)可 以延后取消请求,
并在该线程处理取消请求时执行特定于应用程序的清理操作。
通过pthread取消功能,可以对线程进行异步终止或延迟终止。异步取消可以随时发 生,而延迟取消
只能发生在所定义的点。延迟取消是缺省类型。
线程同步
使用同步功能,可以控制程序流并访问共享数据,从而并发执行多个线程。
共有四种同步模型:互斥锁、读写锁、条件变量和信号。
■ 互斥锁仅允许每次使用一个线程来执行特定的部分代码或者访问特定数据。
■ 读写锁允许对受保护的共享资源进行并发读取和独占写入。要修改资源,线程必须 首先获取互斥写锁。只有释放所有的读锁之后,才允许使用互斥写锁。
■ 条件变量会一直阻塞线程,直到特定的条件为真。
■ 计数信号量通常用来协调对资源的访问。使用计数,可以限制访问某个信号的线程 数量。达到指定的计数时,信号将阻塞。