博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POSIX 线程-------线程库
阅读量:4180 次
发布时间:2019-05-26

本文共 8649 字,大约阅读时间需要 28 分钟。

创建缺省线程

如果未指定属性对象,则该对象为 NULL,系统会创建具有以下属性的缺省线程:

■ 进程范围
■ 非分离
■ 缺省栈和缺省栈大小
■ 零优先级

pthread_create语法

使用 pthread_create() 可以向当前进程中添加新的受控线程。

int pthread_create(pthread_t *tid, const pthread_attr_t *tattr,                   void*(*start_routine)(void *), void *arg);
#include 
pthread_attr_t() tattr;pthread_t tid;extern void *start_routine(void *arg);void *arg;int ret;/* default behavior*/ret = pthread_create(&tid, NULL, start_routine, arg);/* initialized with default attributes */ret = pthread_attr_init(&tattr);/* default behavior specified*/ret = pthread_create(&tid, &tattr, start_routine, arg);

tid为线程id,tattr为线程属性对象,start_routine 是新线程最先执行的函数。当 start_routine 返回时,该线程将退出,其退出状态设置为由 start_routine 返回的值。当 pthread_create() 成功时,所创建线程的 ID 被存储在由 tid 指向的位置中。使用 NULL 属性参数或缺省属性调用pthread_create() 时,pthread_create() 会创建一个缺省线程。在对 tattr 进行初始化之后,该线程将获得缺省行为。

pthread_create返回值pthread_create() 在调用成功完成之后返回零。其他任何返回值都表示出现了错误。如果检测到以下任一情况,pthread_create() 将失败并返回相应的值。

EAGAIN

描述:超出了系统限制,如创建的线程太多。
EINVAL
描述: tattr的值无效。

等待线程终止

pthread_join() 函数会一直阻塞调用线程,直到指定的线程终止。

int pthread_join(thread_t tid, void **status);
#include 
pthread_t tid;int ret;void *status;/* waiting to join thread "tid" with status */ret = pthread_join(tid, &status);/* waiting to join thread "tid" without status */ret = pthread_join(tid, NULL);

指定的线程必须位于当前的进程中,而且不得是分离线程。有关线程分离的信息,当 status 不是 NULL 时,status 指向某个位置,在 pthread_join() 成功返回时,将该位置设置为已终止线程的退出状态。如果多个线程等待同一个线程终止,则所有等待线程将一直等到目标线程终止。然后,一个等待线程成功返回。其余的等待线程将失败并返回 ESRCH 错误。在 pthread_join() 返回之后,应用程序可回收与已终止线程关联的任何数据存储空间。

调用成功完成后,pthread_join() 将返回零。其他任何返回值都表示出现了错误。如果检测到以下任一情况,pthread_join() 将失败并返回相应的值。

ESRCH

描述:没有找到与给定的线程 ID相对应的线程。
EDEADLK
描述: 将出现死锁,如一个线程等待其本身,或者线程A和线程 B 互相等待。
EINVAL
描述:与给定的线程 ID相对应的线程是分离线程。

pthread_join() 仅适用于非分离的目标线程。如果没有必要等待特定线程终止之后才进行其他处理,则应当将该线程分离。

分离线程

pthread_detach() 是 pthread_join() 的替代函数,可回收创建时 detachstate 属性设置为PTHREAD_CREATE_JOINABLE 的线程的存储空间。

int pthread_detach(thread_t tid);
#include 
pthread_t tid;int ret;/* detach thread tid */ret = pthread_detach(tid);

pthread_detach() 函数用于指示应用程序在线程 tid 终止时回收其存储空间。如果 tid 尚未终止,pthread_detach() 不会终止该线程。

pthread_detach() 在调用成功完成之后返回零。其他任何返回值都表示出现了错误。如果检测到以下任一情况,pthread_detach() 将失败并返回相应的值。

EINVAL

描述: tid是分离线程。
ESRCH
描述: tid不是当前进程中有效的未分离的线程。

为线程特定数据创建键

单线程 C 程序有两类基本数据:局部数据和全局数据。对于多线程 C 程序,添加了第三类数据:线程特定数据。线程特定数据与全局数据非常相似,区别在于前者为线程专有。线程特定数据基于每线程进行维护。TSD(特定于线程的数据)是定义和引用线程专用数据的唯一方法。每个线程特定数据项都与一个作用于进程内所有线程的键关联。通过使用key,线程可以访问基于每线程进行维护的指针 (void *)。

int pthread_key_create(pthread_key_t *key,void (*destructor) (void *));
#include 
pthread_key_t key;int ret;/* key create without destructor */ret = pthread_key_create(&key, NULL);/* key create with destructor */ret = pthread_key_create(&key, destructor);

可以使用 pthread_key_create() 分配用于标识进程中线程特定数据的键。键对进程中的所有线程来说是全局的。创建线程特定数据时,所有线程最初都具有与该键关联的 NULL值。使用各个键之前,会针对其调用一次 pthread_key_create()。不存在对键(为进程中所有的线程所共享)的隐含同步。创建键之后,每个线程都会将一个值绑定到该键。这些值特定于线程并且针对每个线程单独维护。如果创建该键时指定了 destructor 函数,则该线程终止时,系统会解除针对每线程的绑定。当 pthread_key_create() 成功返回时,会将已分配的键存储在 key 指向的位置中。调用方必须确保对该键的存储和访问进行正确的同步。使用可选的析构函数 destructor 可以释放过时的存储。如果某个键具有非 NULL destructor函数,而线程具有一个与该键关联的非 NULL 值,则该线程退出时,系统将使用当前的相关值调用 destructor 函数。destructor 函数的调用顺序不确定。

pthread_key_create() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_key_create() 将失败并返回相应的值。

EAGAIN

描述: key名称空间已经用完。
ENOMEM
描述:此进程中虚拟内存不足,无法创建新键。

删除线程特定数据键

使用 pthread_key_delete() 可以销毁现有线程特定数据键。由于键已经无效,因此将释放与该键关联的所有内存。引用无效键将返回错误。Solaris 线程中没有类似的函数。

int pthread_key_delete(pthread_key_t key);
#include 
pthread_key_t key;int ret;/* key previously created */ret = pthread_key_delete(key);

如果已删除键,则使用调用 pthread_setspecific() 或 pthread_getspecific() 引用该键时,生成的结果将是不确定的。程序员在调用删除函数之前必须释放所有线程特定资源。删除函数不会调用任何析构函数。反复调用 pthread_key_create() 和 pthread_key_delete() 可能会产生问题。如果pthread_key_delete() 将键标记为无效,而之后 key 的值不再被重用,那么反复调用它们就会出现问题。对于每个所需的键,应当只调用 pthread_key_create() 一次。

pthread_key_delete() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_key_delete() 将失败并返回相应的值。

EINVAL

描述: key的值无效。

设置线程特定数据

使用 pthread_setspecific() 可以为指定线程特定数据键设置线程特定绑定。

int pthread_setspecific(pthread_key_t key, const void *value);
#include 
pthread_key_t key;void *value;int ret;/* key previously created */ret = pthread_setspecific(key, value);

pthread_setspecific() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_setspecific() 将失败并返回相应的值。

ENOMEM

描述:虚拟内存不足。
EINVAL
描述: key无效。

设置新绑定时,pthread_setspecific()不会释放其存储空间。必须释放现有绑定,否则会出现内存泄漏。

获取线程特定数据

使用 pthread_getspecific() 获取调用线程的键绑定,并将该绑定存储在 value 指向的位置中。

void *pthread_getspecific(pthread_key_t key);
#include 
pthread_key_t key;void *value;/* key previously created */value = pthread_getspecific(key);

pthread_getspecific 不返回任何错误。

获取线程标识符

使用 pthread_self() 获取调用线程的 thread identifier。

pthread_t pthread_self(void);
#include 
pthread_t tid;tid = pthread_self();

pthread_self() 返回调用线程的 thread identifier。

比较线程ID

使用 pthread_equal() 对两个线程的线程标识号进行比较。

int pthread_equal(pthread_t tid1, pthread_t tid2);
#include 
pthread_t tid1, tid2;int ret;ret = pthread_equal(tid1, tid2);

如果 tid1 和 tid2 相等,pthread_equal() 将返回非零值,否则将返回零。如果 tid1 或 tid2 是无效的线程标识号,则结果无法预测。

初始化线程

使用 pthread_once(),可以在首次调用 pthread_once 时调用初始化例程。以后调用pthread_once() 将不起作用。

int pthread_once(pthread_once_t *once_control,void (*init_routine)(void));
#include 
pthread_once_t once_control = PTHREAD_ONCE_INIT;int ret;ret = pthread_once(&once_control, init_routine);

once_control 参数用来确定是否已调用相关的初始化例程。

pthread_once() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_once() 将失败并返回相应的值。

EINVAL

描述: once_control 或 init_routine 是 NULL。

停止执行线程

使用 sched_yield(),可以使当前线程停止执行,以便执行另一个具有相同或更高优先级的线程。

int sched_yield(void);
#include 
int ret;ret = sched_yield();

sched_yield() 在成功完成之后返回零。否则,返回 -1,并设置 errno 以指示错误状态。

ENOSYS

描述:本实现不支持sched_yield。

设置线程的优先级

请使用 pthread_setschedparam(3C) 修改现有线程的优先级。此函数对于调度策略不起作用。

int pthread_setschedparam(pthread_t tid, int policy,const struct sched_param *param);
#include 
pthread_t tid;int ret;struct sched_param param;int priority;/* sched_priority will be the priority of the thread */sched_param.sched_priority = priority;policy = SCHED_OTHER;/* scheduling parameters of target thread */ret = pthread_setschedparam(tid, policy, &param);

pthread_setschedparam() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_setschedparam() 函数将失败并返回相应的值。

EINVAL

描述:所设置属性的值无效。
ENOTSUP
描述:尝试将该属性设置为不受支持的值。

获取线程的优先级

pthread_getschedparam() 可用来获取现有线程的优先级。

int pthread_getschedparam(pthread_t tid, int policy,struct schedparam *param);
#include 
pthread_t tid;sched_param param;int priority;int policy;int ret;/* scheduling parameters of target thread */ret = pthread_getschedparam (tid, &policy, &param);/* sched_priority contains the priority of the thread */priority = param.sched_priority;

pthread_getschedparam() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

ESRCH

描述: tid指定的值不引用现有的线程。

向线程发送信号

使用 pthread_kill() 向线程发送信号。

int pthread_kill(thread_t tid, int sig);
#include 
#include
int sig;pthread_t tid;int ret;ret = pthread_kill(tid, sig);

pthread_kill() 将信号 sig 发送到由 tid 指定的线程。tid 所指定的线程必须与调用线程在同一个进程中。sig 参数必须来自 signal(5) 提供的列表。如果 sig 为零,将执行错误检查,但并不实际发送信号。此错误检查可用来检查 tid 的有效性。

pthread_kill() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_kill() 将失败并返回相应的值。

EINVAL

描述:sig是无效的信号量。
ESRCH
描述:当前的进程中找不到tid。

访问调用线程的信号掩码

使用 pthread_sigmask() 更改或检查调用线程的信号掩码。

int pthread_sigmask(int how, const sigset_t *new, sigset_t *old);
#include 
#include
int ret;sigset_t old, new;ret = pthread_sigmask(SIG_SETMASK, &new, &old); /* set new mask */ret = pthread_sigmask(SIG_BLOCK, &new, &old); /* blocking mask */ret = pthread_sigmask(SIG_UNBLOCK, &new, &old); /* unblocking */

how 用来确定如何更改信号组。how 可以为以下值之一:

■ SIG_BLOCK。向当前的信号掩码中添加 new,其中 new 表示要阻塞的信号组。
■ SIG_UNBLOCK。从当前的信号掩码中删除 new,其中 new 表示要取消阻塞的信号组。
■ SIG_SETMASK。将当前的信号掩码替换为 new,其中 new 表示新的信号掩码。
当 new 的值为 NULL 时,how 的值没有意义,线程的信号掩码不发生变化。要查询当前已阻塞的信号,请将 NULL 值赋给 new 参数。除非 old 变量为 NULL,否则 old 指向用来存储以前的信号掩码的空间。

pthread_sigmask() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_sigmask() 将失败并返回相应的值。

EINVAL

描述:未定义 how的值。

终止线程

使用 pthread_exit() 终止线程。

void pthread_exit(void *status);
#include 
void *status;pthread_exit(status); /* exit with status */

pthread_exit() 函数可用来终止调用线程。将释放所有线程特定数据绑定。如果调用线程尚未分离,则线程 ID 和 status 指定的退出状态将保持不变,直到应用程序调用pthread_join() 以等待该线程。否则,将忽略 status。线程 ID 可以立即回收。

调用线程将终止,退出状态设置为 status 的内容。

取消线程

使用 pthread_cancel() 取消线程。

int pthread_cancel(pthread_t thread);
#include 
pthread_t thread;int ret;ret = pthread_cancel(thread);

取消请求的处理方式取决于目标线程的状态。状态由以下两个函数确定:pthread_setcancelstate() 和 pthread_setcanceltype()。

pthread_cancel() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

ESRCH

描述:没有找到与给定线程 ID相对应的线程。

转载地址:http://snrai.baihongyu.com/

你可能感兴趣的文章
JAVA常用基础类
查看>>
简述Java异常处理
查看>>
简述Java集合框架
查看>>
jQuery+ajax实现省市区(县)下拉框三级联动
查看>>
Spring中的AOP 面向切面编程
查看>>
简述Spring中的JDBC框架
查看>>
MyBatis 动态SQL
查看>>
Spring MVC体系结构和处理请求控制器
查看>>
浏览器内核的整理稿
查看>>
暴力搜索内存空间获得API的线性地址
查看>>
CTF编码
查看>>
万能密码原理和总结
查看>>
缓冲区溢出学习
查看>>
Excel高级使用技巧
查看>>
速算,以后留着教孩子
查看>>
让你变成ps高手
查看>>
在可执行jar中动态载入第三方jar(转贴)
查看>>
考虑体积重量的01背包问题—基于遗传算法
查看>>
K-means 聚类算法
查看>>
带约束的K-means聚类算法
查看>>