1作用编辑
线程库实现了POSIX线程标准,通常称为Pthreads。 POSIX线程具有很好的可移植性,用pthreads编写的代码可以在Solaris、FreeBSD、Linux等平台上运行,Windows平台上也有pthreads-win32
[1]。
Pthreads定义了一组c语言类型、函数和常量,并在pthread.h头文件和线程库中实现。
[2-3]。
2数据类型编辑
pthread_t :线程句柄
pthread_attr_t :线程属性
3操作函数编辑
pthread_create (:创建线程
pthread_exit (:结束当前线程
pthread_cancel () :中断另一个线程的执行
pthread_join (:阻止当前线程直到另一个线程结束
pthread_attr_init (:初始化线程的属性
pthread_attr_setdetachstate (:设置关闭状态的属性,以确定退出时是否可以合并线程
pthread_attr_getdetachstate (:获取脱离状态的属性
pthread_attr_destroy (:删除线程的属性
pthread_kill (:向线程发送信号
4同步函数编辑
用于mutex和条件变量
pthread_mutex_init ()初始化互斥锁
删除pthread_mutex_destroy ()独占锁
pthread_mutex_lock (:占用独占锁(块操作) )
pthread_mutex_trylock (:尝试占用独占锁(不阻止操作) )。 即,互斥锁空闲时,占用该锁; 否则,我马上回来。
pthread_mutex_unlock () :解除互斥锁
pthread_cond_init (:初始化条件变量
pthread_cond_destroy (:放弃条件变量
pthread_cond_signal () :调用pthread_cond_wait )来触发进入休眠的第一个线程
pthread_cond_wait () :等待条件变量的特殊条件出现
Thread-local storage (
线程特定的数据) :
pthread_key_create () :为进程中的线程分配一个标识特定数据的密钥
pthread_setspecific () :设置给定线程特定的数据密钥的线程特定绑定
pthread_getspecific () :获取调用线程的密钥绑定,并将其存储在value指向的位置
pthread_key_delete () :丢弃现有线程特定的数据密钥
pthread_attr_getschedparam (; 获取线程优先级
pthread_attr_setschedparam (; 设置线程优先级
5编辑工具函数
pthread_equal () :比较两个线程的线程标识号
pthread_detach () :分离线程
pthread_self () :查询线程本身的线程标识号
6数据运用编辑
函数应用背景:在单线程程序中,函数经常使用全局变量或静态变量。 这并不影响程序的准确性,但如果多线程调用的函数使用全局或静态变量,则很可能会导致编程错误。 由于这些函数使用的全局和静态变量不能存储不同线程的值,因此如果几乎同时调用同一进程中的不同线程,则可能会出现问题。 解决此问题的一种方法是使用线程特定数据的机制。
这里引入一个简单的程序实例,作为介绍线程特定数据的案例。
线程特定的数据:
可以想象,在多线程程序中,如果每个线程按顺序调用函数a和函数b,则b显示的字符串可能不是用a设置的字符串,因此某些线程可能无法获得预期的显示结果。 这两个函数非常简单,但本章足以说明线程特定数据的含义。 这是因为这表示两个函数使用线程特定的数据机制的典型情况,即多个函数使用同一全局变量的情况。
实现POSIX的系统在每个进程中都必须维护一个称为Key的结构数组。 此数组中的每个结构都称为线程特定的数据元素。 在POSIX上,系统实现的Key结构数组必须包含至少128个线程特定的数据元素,并且每个线程特定的数据元素至少必须包含两个内容。 这意味着使用标志和析构函数的指针。 线程特定数据元素中的使用标志指示是否正在使用此数组元素。 初始值为“未使用”。 稍后将介绍线程特定数据元素中析构函数的指针。 以下说明假设Key结构数组包含128个元素。
Key结构数组中各元素的电缆
引 (0~127) 称 之 为 键 (key) 当 一 个 线 程 调 用,pthread_key_create 创建一个新的线程特定 数据元素时,系统搜索其所在进程的 Key 结构 数组,找出其中第一个不在使用的元素,并返回该元素的键。这个函数的形式为:[4]
参数 keyptr 为一个 pthread_key_t 变量的 指针,用于保存得到的键值。参数 destructor为指定的 析构函数的 指针。除了 Key 结构 数组,系统还在进程中维护关于每个线程的多种信息。这些特定于 线程的信息被保存于称之为 Pthread 的结构中。Pthread 结构中包含名为 pkey 的 指针数组,其长度为128,初始值为空。这 128 个 指针与 Key 结构 数组的 128 个线程特定 数据元素一一对应。在调用 pthread_key_create 得到一个键之后,每个 线程可以依据这个键操作自己的 pkey 指针数组中对应的指针,这通过 pthread_getspecific 和 pthread_setspecific 函数来实现。这两个函数的形式为:
[5]
pthread_getspecific 返回 pkey 中对应于 key 的 指针,而 pthread_setspecific 将 pkey 中对应于 key 的指针设置为 value。我们使用 线程特定数据机制,就是要使线程中的函数可以共享一些数据。如果我们在 线程中通过 malloc 获得一块内存,并把这块内存的 指针通过 pthread_setspecific 设置到 pkey 指针数组中对应于 key 的位置,那么线程中调用的函数即可通过 pthread_getspecific 获得这个指针,这就实现了线程内部数据在各个函数间的共享。当一个 线程终止时,系统将扫描该线程的 pkey 数组,为每个非空的 pkey 指针调用相应的 析构函数,因此只要将执行回收的函数的指针在调用 pthread_key_create 时作为函数的参数,即可在线程终止时自动回收分配的内存区