chap2基本线程编程

weixin_38065208 2008-05-01 02:52:19

1.等待线程终止 pthread_join() 函数会一直阻塞调用线程,直到指定的线程终止。 指定的线程必须位于当前的进程中,而且不得是分离线程。 如果多个线程等待同一个线程终止,则所有等待线程将一直等到目标线程终止。然后,一 个等待线程成功返回。其余的等待线程将失败并返回 ESRCH 错误。 在 pthread_join() 返回之后,应用程序可回收与已终止线程关联的任何数据存储空间。 ESRCH    描述: 没有找到与给定的线程 ID 相对应的线程。 EDEADLK    描述: 将出现死锁,如一个线程等待其本身,或者线程 A 和线程 B 互相等待。 EINVAL    描述: 与给定的线程 ID 相对应的线程是分离线程。 pthread_join() 仅适用于非分离的目标线程。如果没有必要等待特定线程终止之后才进行 其他处理,则应当将该线程分离。 2.分离线程 int pthread_detach(thread_t tid); 可回收创建时 detachstate 属性设置为PTHREAD_CREATE_JOINABLE 的线程的存储空间。 pthread_detach() 函数用于指示应用程序在线程 tid 终止时回收其存储空间。如果 tid 尚未终 止,pthread_detach() 不会终止该线程。 3.为线程特定数据创建键 单线程 C 程序有两类基本数据:局部数据和全局数据。对于多线程 C 程序,添加了第三类 数据:线程特定数据。线程特定数据与全局数据非常相似,区别在于前者为线程专有。 线程特定数据基于每线程进行维护。TSD(特定于线程的数据)是定义和引用线程专用数 据的唯一方法。每个线程特定数据项都与一个作用于进程内所有线程的键关联。通过使用 key,线程可以访问基于每线程进行维护的指针 (void *)。 int    pthread_key_create(pthread_key_t *key, void (*destructor) (void *)); 可以使用 pthread_key_create(3C) 分配用于标识进程中线程特定数据的键。键对进程中的 所有线程来说是全局的。创建线程特定数据时,所有线程最初都具有与该键关联的 NULL 值。 使用各个键之前,会针对其调用一次 pthread_key_create()。不存在对键(为进程中所有 的线程所共享)的隐含同步。 创建键之后,每个线程都会将一个值绑定到该键。这些值特定于线程并且针对每个线程单 独维护。如果创建该键时指定了 destructor 函数,则该线程终止时,系统会解除针对每线 程的绑定。 当 pthread_key_create() 成功返回时,会将已分配的键存储在 key 指向的位置中。调用方必 须确保对该键的存储和访问进行正确的同步。 使用可选的析构函数 destructor 可以释放过时的存储。如果某个键具有非 NULL destructor 函数,而线程具有一个与该键关联的非 NULL 值,则该线程退出时,系统将使用当前的相关 值调用 destructor 函数。destructor 函数的调用顺序不确定。 4.删除线程特定数据键 int pthread_key_delete(pthread_key_t key); 如果已删除键,则使用调用 pthread_setspecific() 或 pthread_getspecific() 引用该键 时,生成的结果将是不确定的。 程序员在调用删除函数之前必须释放所有线程特定资源。删除函数不会调用任何析构函 数。反复调用 pthread_key_create() 和 pthread_key_delete() 可能会产生问题。如果 pthread_key_delete() 将键标记为无效,而之后 key 的值不再被重用,那么反复调用它们就 会出现问题。对于每个所需的键,应当只调用 pthread_key_create() 一次。 5.设置线程特定数据 int pthread_setspecific(pthread_key_t key, const void *value); 为指定线程特定数据键设置线程特定绑定。 注 – 设置新绑定时,pthread_setspecific() 不会释放其存储空间。必须释放现有绑定,否 则会出现内存泄漏。 6.获取线程特定数据 使用 pthread_getspecific获取调用线程的键绑定,并将该绑定存储在 value 指向的 位置中。 void *pthread_getspecific(pthread_key_t key); 7.初始化线程 使用 pthread_once,可以在首次调用 pthread_once 时调用初始化例程。以后调用 pthread_once() 将不起作用。 pthread_once_t once_control = PTHREAD_ONCE_INIT; int     pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); 8.停止执行线程 使用 sched_yield,可以使当前线程停止执行,以便执行另一个具有相同或更高优先级的线程。 int sched_yield(void); 9.设置线程的优先级 请使用 pthread_setschedparam 修改现有线程的优先级。此函数对于调度策略不起作用。 int     pthread_setschedparam(pthread_t tid, int policy, const struct sched_param *param); 10.获取线程的优先级 int     pthread_getschedparam(pthread_t tid, int policy, struct schedparam *param); 11.向线程发送信号 int pthread_kill(thread_t tid, int sig); pthread_kill() 将信号 sig 发送到由 tid 指定的线程。tid 所指定的线程必须与调用线程在同 一个进程中。sig 参数必须来自 signal(5) 提供的列表。 如果 sig 为零,将执行错误检查,但并不实际发送信号。此错误检查可用来检查 tid 的有效 性。 12.访问调用线程的信号掩码 使用 pthread_sigmask更改或检查调用线程的信号掩码。 int pthread_sigmask(int how, const sigset_t *new, sigset_t *old); SIG_BLOCK。向当前的信号掩码中添加 new,其中 new 表示要阻塞的信号组。 SIG_UNBLOCK。从当前的信号掩码中删除 new,其中 new 表示要取消阻塞的信号组。 SIG_SETMASK。将当前的信号掩码替换为 new,其中 new 表示新的信号掩码。 当 new 的值为 NULL 时,how 的值没有意义,线程的信号掩码不发生变化。要查询当前已阻 塞的信号,请将 NULL 值赋给 new 参数。 除非 old 变量为 NULL,否则 old 指向用来存储以前的信号掩码的空间。 13.安全地 Fork int pthread_atfork(void (*prepare) (void), void (*parent) (void), void (*child)(void) ); pthread_atfork 返回值: pthread_atfork() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现 以下情况,pthread_atfork() 将失败并返回相应的值。 ENOMEM    描述: 表空间不足,无法记录 Fork 处理程序地址。 14.终止线程 void pthread_exit(void *status); pthread_exit() 函数可用来终止调用线程。将释放所有线程特定数据绑定。如果调用线程 尚未分离,则线程 ID 和 status 指定的退出状态将保持不变,直到应用程序调用 pthread_join() 以等待该线程。否则,将忽略 status。 pthread_exit 返回值: 调用线程将终止,退出状态设置为 status 的内容。 15.线程的终止方式:(3种) (1).从线程的第一个(最外面的)过程返回,即线程启动例程。请参见 pthread_create。 (2).调用 pthread_exit(),提供退出状态。 (3).使用 POSIX 取消函数执行终止操作。请参见 pthread_cancel()。 线程的缺省行为是拖延,直到其他线程通过 "joining" 拖延线程确认其已死亡。此行为与非 分离的缺省 pthread_create() 属性相同,join 的结果是 joining 线程得到已终止线程 的退出状态,已终止的线程将消失。 有一个重要的特殊情况,即当初始线程(即调用 main() 的线程)从 main() 调用返回时或调 用 exit() 时,整个进程及其所有的线程将终止。因此,一定要确保初始线程不会从 main() 过早地返回。 请注意,如果主线程仅仅调用了 pthread_exit,则仅主线程本身终止。进程及进程内的其 他线程将继续存在。所有线程都已终止时,进程也将终止。 16.取消线程 取消点 仅当取消操作安全时才应取消线程。pthreads 标准指定了几个取消点,其中包括:   通过 pthread_testcancel 调用以编程方式建立线程取消点。   线程等待 pthread_cond_wait 或 pthread_cond_timedwait(3C) 中的特定条件出现。   被 sigwait(2) 阻塞的线程。   一些标准的库调用。通常,这些调用包括线程可基于其阻塞的函数。有关列表,请参见      cancellation(5)册页。 缺省情况下将启用取消功能。 放置取消点 执行取消操作存在一定的危险。大多数危险都与完全恢复不变量和释放共享资源有关。取 消线程时一定要格外小心,否则可能会使互斥保留为锁定状态,从而导致死锁。或者,已 取消的线程可能保留已分配的内存区域,但是系统无法识别这一部分内存,从而无法释放 它。 互斥肯定不是取消点 请将异步取消区域限制在没有外部依赖性的序列,因为外部依赖性可能会产生挂起的资源 或未解决的状态条件。在从某个备用的嵌套取消状态返回时,一定要小心地恢复取消状 态。该接口提供便于进行恢复的功能:pthread_setcancelstate(3C) 在所引用的变量中保留 当前的取消状态,pthread_setcanceltype(3C) 以同样的方式保留当前的取消类型。 无论何时,都应注意资源和状态恢已复到与起点一致的状态。 17.启用或禁用取消功能 请使用 pthread_setcancelstate启用或禁用线程取消功能。创建线程时,缺省情况下线 程取消功能处于启用状态。 int pthread_setcancelstate(int state, int *oldstate); 18.设置取消类型 使用 pthread_setcanceltype可以将取消类型设置为延迟或异步模式。 int pthread_setcanceltype(int type, int *oldtype); 创建线程时,缺省情况下会将取消类型设置为延迟模式。在延迟模式下,只能在取消点取 消线程。在异步模式下,可以在执行过程中的任意一点取消线程。因此建议不使用异步模 式。 PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_ASYNCHRONOUS 19.创建取消点 void pthread_testcancel(void); 当线程取消功能处于启用状态且取消类型设置为延迟模式时,pthread_testcancel() 函数 有效。如果在取消功能处于禁用状态下调用 pthread_testcancel(),则该函数不起作用。 请务必仅在线程取消操作安全的序列中插入 pthread_testcancel()。除通过 pthread_testcancel() 调用以编程方式建立的取消点以外,pthread 标准还指定了几个取消 点。 20.将处理程序推送到栈上 使用清理处理程序,可以将状态恢复到与起点一致的状态,其中包括清理已分配的资源和 恢复不变量。使用 pthread_cleanup_push 和 pthread_cleanup_pop 函数可以管理清 理处理程序。 在程序的同一词法域中可以推送和弹出清理处理程序。推送和弹出操作应当始终匹配,否 则会生成编译器错误。 使用 pthread_cleanup_push 将清理处理程序推送到清理栈 (LIFO)。 void pthread_cleanup_push(void(*routine)(void *), void *args); 21.从栈中弹出处理程序 使用 pthread_cleanup_pop 从清理栈中弹出清理处理程序。 void pthread_cleanup_pop(int execute); 如果弹出函数中的参数为非零值,则会从栈中删除该处理程序并执行该处理程序。如果该 参数为零,则会弹出该处理程序,而不执行它。 线程显式或隐式调用 pthread_exit 时,或线程接受取消请求时,会使用非零参数有效地 调用 pthread_cleanup_pop()。                                                 本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/41113/showart_653812.html
...全文
18 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

435

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧