1、线程创建和结束
#include<pthread.h>
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine)(void*), void* arg)
void pthread_exit(void* retval)
pthread_create 函数用于创建一个新线程,参数信息如下:
- thread参数为新线程的标识符,是一个整型类型数。
- attr参数用于设置新线程的属性,如果为NULL则表示使用默认属性。
- start_routine参数为新线程入口函数。
- arg参数为新线程入口函数的参数。
- pthread_create函数成功返回0,失败时返回错误码。
pthread_exit函数结束线程,并通过参数retval向线程回收者返回退出信息。它执行完之后不会返回到调用者,而且此函数不会出现调用失败。
2、线程回收和终止
#include<pthread.h>
int pthread_join(pthread_t thread, void** retval);
int pthread_cancel(pthread_t thread);
pthread_join函数用来回收其他线程(目标线程是可回收的),等待线程结束,类似于进程回收函数wait和waitpid调用。thread参数指定要回收的线程标识符,retval参数则是目标线程结束时返回的退出信息。此函数为阻塞的,直到目标线程结束,实现回收为止。函数调用成功返回0,失败返回错误码,错误码如下:EDEADLK,出现死锁,死锁的原因可能是两线程相互调用那pthread_join或者一个线程对自己调用pthread_join;EINVAL,目标线程不可回收或已有其他线程在回收该目标线程;ESRCH,目标线程不存在。
pthread_cancel函数用于异常终止一个线程,函数调用成功返回0,失败返回错误码。不过,接收到终止请求的线程可以决定是否允许被终止,这可以由以下两个函数来设置:
#include<pthread.h>
int pthread_setcancelstate(int state, int* oldstate)
int pthread_setcanceltype(int type, int* oldtype)
第一个函数用于设置是否允许被终止,state参数可选值为:PTHREAD_CANCEL_ENABLE,允许线程被终止,线程创建时默认状态;PTHREAD_CANCEL_DISABLE,不允许被终止,如果这种状态下的线程收到终止请求,则会将请求挂起,直到该线程允许被终止。
第二个函数用于设置终止方式,type参数可选值为:PTHREAD_CANCEL_ASYNCHRONOUS,线程随时都可以被终止;PTHREAD_CANCEL_DEFERRED,允许目标线程推迟终止行动,直到它调用了终止点函数(pthread_join,pthread_testcancel,pthread_cond_wait,pthread_cond_timedwait,sem_wait,sigwait,read,wait等),通常我们在可能被终止的代码中调用pthread_testcancel函数来设置终止点。
3、线程属性
线程属性由pthread_addr_t结构定义,pthread_addr_t结构为一个共用体,主要包括一个字符数组,各种属性都包含在字符数组中,线程库定义了一系列的函数来操作pthread_addr_t类型的变量,以获取或设置线程属性。这里就不罗列这些函数,而是介绍一些重要的属性含义。
- detachstate,线程的脱离状态。两个可选值,PTHREAD_CREATE_JOINABLE,指定线程为可以被回收的;PTHREAD_CREATE_DETACH,设置线程为脱离线程,即脱离与进程中的其他线程同步。脱离线程在退出时自行释放其占有的系统资源。PTHREAD_CREATE_JOINABLE为默认情况,可以使用pthread_detach函数来修改为脱离线程。
- stackaddr,线程堆栈的起始地址。
- stacksize,线程堆栈大小,一般不需要用户来管理线程堆栈,Linux默认给每个线程分配堆栈空间(默认8M),可以使用ulimt -s命令来查看或修改默认值。
- guardsize,保护区域大小。
- schedparam,线程调度参数,类型为sched_param结构,结构中只有一个整型类型的成员sched_priority,即线程运行的优先级。
- schedpolicy,线程调度策略。
- inheritsched,是否继承调用线程的调度属性。如果继承,则后续再设置新线程的调度参数属性将没有任何效果,如果不继承,则需要明确指明新线程的调度参数。
- scope,线程间竞争CPU的范围,即线程优先级的有效范围。