简介
在共享内存的多处理器结构中,可以用线程来实现并行。对于UNIX系统, IEEE POSIX 1003.1c标准规定了C语言线程编程接口的标准。这份标准的实现就是POSIX threads, 或者称为Pthreads.
本文开始先介绍线程的基本概念,动机和设计方面的一些考虑。 接下来是Pthreads API 的三个主要部分:线程管理,互斥锁和 条件变量。本文自始至终会贯穿大量的示例代码来展示如何使用Pthread API的每一部分。
Pthreads 概述
线程是什么?
从技术角度讲,一个线程是一个独立的指令流可以被操作系统调用运行。But what does this mean?
从程序员的角度讲,独立于主程序而单独运行的“程序”可以被称为一个线程。
更进一步的讲, 想象一个包含很多子程序的主程序 (a.out) . 然后想象所有这些子程序都能操作系统调用同时并且独立的运行。这就是一个多线程的程序。
这是怎么完成的呢?
在理解线程之前, 先要理解UNIX系统下的进程。 一个进程是由操作系统创建的, 并且要求大量的"开销"。进程包含关于程序资源的信息和程序的执行状态,包括:
进程ID,进程组ID, 用户ID,和组ID
环境
工作目录
程序指令
寄存器
栈
堆
文件描述符
信号操作
共享库
进程通信工具 (例如消息队列,管道,信号量,或者共享内存 ).
UNIX进程 线程
线程使用并存在在这些进程资源中,线程可以被操作系统调用并独立运行, 很大程度上是因为它只复制了很少量的作为可执行代码存在的必须重要资源。
一个线程完成独立的控制流是因为它维护自己拥有的:
栈指针
寄存器
调度优先级
待定和阻塞信号集合
线程特有的数据
因此,简而言之,在UNIX系统环境中一个线程:
存在在一个进程中并使用进程资源
只要父进程存在并且操作系统支持就一直拥有自己独立的控制流
仅复制独立调度所必须关键资源
可以和其他线程共享进程资源
如果线程的父进程死掉,则该线程死掉
是“轻量级”的因为大多是开销在它的进程创建的时候已经完成了
同一进程的线程间共享资源,导致:
一个线程对于共享的系统资源所做的更改(例如关闭一个文件)将会被所有其他的线程发现
两个具有相同值的指针指向相同的数据
可能读写相同的内层位置,因此要求程序员进行显式的同步