线程库
下面简要论述了特定任务及其相关手册页。
创建缺省线程
如果未指定属性对象,则该对象为NULL,系统会创建具有以下属性的缺省线程:
■ 进程范围
■ 非分离
■ 缺省栈和缺省栈大小
■ 零优先级
还可以用pthread_attr_init()
创建缺省属性对象,然后使用该属性对象来创建缺省线
程。
pthread_create
语法
使用pthread_create(3C)
可以向当前进程中添加新的受控线程。
int pthread_create(pthread_t *tid, const pthread_attr_t *tattr,
void*(*start_routine)(void *), void *arg);
#include <pthread.h>
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);
使用具有必要状态行为的attr 调用pthread_create()
函数。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()
函数会一直阻塞调用线程,直到指定的线程终止。
pthread_join
语法
使用pthread_join(3C)
等待线程终止。
int pthread_join(thread_t tid, void **status);
#include <pthread.h>
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()
将返回零。其他任何返回值都表示出现了错误。如
果检测到以下任一情况,pthread_join()
将失败并返回相应的值。
ESRCH
描述: 没有找到与给定的线程ID 相对应的线程。
EDEADLK
描述: 将出现死锁,如一个线程等待其本身,或者线程A 和线程B 互相等待。
EINVAL
描述: 与给定的线程ID 相对应的线程是分离线程。
pthread_join()
仅适用于非分离的目标线程。如果没有必要等待特定线程终止之后才
进行其他处理,则应当将该线程分离。
简单线程的示例
在示例1 中,一个线程执行位于顶部的过程,该过程首先创建一个辅助线程来执行
fetch()
过程。fetch()
执行复杂的数据库查找操作,查找过程需要花费一些时间。
主线程将等待查找结果,但同时还执行其他操作。因此,主线程将执行其他活动,然
后通过执行pthread_join()
等待辅助线程。
将新线程的pbe 参数作为栈参数进行传递。这个线程参数之所以能够作为栈参数传递,
是因为主线程会等待辅助线程终止。不过,首选方法是使用malloc 从堆分配存储,而
不是传递指向线程栈存储的地址。如果将该参数作为地址传递到线程栈存储,则该地
址可能无效或者在线程终止时会被重新分配。
示例1简单线程程序
void mainline (...)
{
struct phonebookentry *pbe;
pthread_attr_t tattr;
pthread_t helper;
void *status;
pthread_create(&helper, NULL, fetch, &pbe);
/* do something else for a while */
pthread_join(helper, &status);
/* it’s now safe to use result */
}
void *fetch(struct phonebookentry *arg)
{
struct phonebookentry *npbe;
/* fetch value from a database */
npbe = search (prog_name)
if (npbe != NULL)
*arg = *npbe;
pthread_exit(0);
}
struct phonebookentry {
char name[64];
char phonenumber[32];
char flags[16];
}
分离线程
pthread_detach(3C)
是pthread_join(3C)
的替代函数,可回收创建时detachstate 属性设
置为PTHREAD_CREATE_JOINABLE
的线程的存储空间。
pthread_detach
语法
int pthread_detach(thread_t tid);
#include <pthread.h>
pthread_t tid;
int ret;
/* detach thread tid */
ret = pthread_detach(tid);
pthread_detach()
函数用于指示应用程序在线程tid 终止时回收其存储空间。如果tid 尚
未终止,pthread_detach()
不会终止该线程。
pthread_detach
返回值
pthread_detach()
在调用成功完成之后返回零。其他任何返回值都表示出现了错误。
如果检测到以下任一情况,pthr