1.0 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
// 功能: 创建一个新线程,执行 start_routine 函数,
// 传递 arg 作为参数,使用 attr 设置新线程的属性
// 参数: thread 线程 ID 号
// attr 新线程的属性,使用默认属性则可以为 NULL
// start_routine 线程要执行的任何的入口函数
// arg 传递给新线程的参数
// 返回值:成功返回 0,失败返回错误号
// 注: 线程结束的情况:
// 1. 线程中调用了 pthread_exit(3),同一个进程中的其它线程
// 可以使用 pthread_join(3) 获取返回值。
// 2. 从 start_routine() 中返回。
// 3. 被 pthread_cancel(3) 取消。
// 4. 进程中的任何线程调用了 exit(3),或主线程返回,
// 进程结束,则线程也结束
* It calls pthread_exit(3), specifying an exit status value that is
available to another thread in the same process that calls
pthread_join(3).
* It returns from start_routine(). This is equivalent to calling
pthread_exit(3) with the value supplied in the return statement.
* It is canceled (see pthread_cancel(3)).
* Any of the threads in the process calls exit(3), or the main thread
performs a return from main(). This causes the termination of all
threads in the process.
2.0 pthread_t pthread_self(void)
#include <pthread.h>
pthread_t pthread_self(void);
Compile and link with -pthread.
// 功能: 获取调用线程的 ID,与 pthread_create 的 *thread 参数同值
// 参数: 无
// 返回值:线程 ID
NAME
pthread_self - obtain ID of the calling thread
SYNOPSIS
#include <pthread.h>
pthread_t pthread_self(void);
Compile and link with -pthread.
DESCRIPTION
The pthread_self() function returns the ID of the calling thread. This
is the same value that is returned in *thread in the pthread_create(3)
call that created this thread.
RETURN VALUE
This function always succeeds, returning the calling thread's ID.
ERRORS
This function always succeeds.
3.0 void pthread_exit(void *retval)
Compile and link with -pthread.
// 功能: 结束调用线程
// 参数: retval 返回值
// 返回值:无
DESCRIPTION
The pthread_exit() function terminates the calling thread and returns a
value via retval that (if the thread is joinable) is available to
another thread in the same process that calls pthread_join(3).
Any clean-up handlers established by pthread_cleanup_push(3) that have
not yet been popped, are popped (in the reverse of the order in which
they were pushed) and executed. If the thread has any thread-specific
data, then, after the clean-up handlers have been executed, the corre‐
sponding destructor functions are called, in an unspecified order.
When a thread terminates, process-shared resources (e.g., mutexes, con‐
dition variables, semaphores, and file descriptors) are not released,
and functions registered using atexit(3) are not called.
After the last thread in a process terminates, the process terminates
as by calling exit(3) with an exit status of zero; thus, process-shared
resources are released and functions registered using atexit(3) are
called.
4.0 int pthread_detach(pthread_t thread);5.0 int pthread_join(pthread_t thread, void **retval);
前言:
1.linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程,这些资源在线程函数退出时 或 pthread_exit时自动会被释放。
2.unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。或者将线程置为 joinable,然后适时调用pthread_join.
3.其实简单的说就是在线程函数头加上 pthread_detach(pthread_self())的话,线程状态改变,在函数尾部直接 pthread_exit线程就会自动退出。省去了给线程擦屁股的麻烦。
int pthread_detach(pthread_t thread);
Compile and link with -pthread.
// 功能: 分离线程 thread
// 当分离的线程结束后,会自动释放资源,而无需其它线程回收
// 参数: thread 要分离的线程 ID
// 返回值:成功返回 0,失败返回错误号
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
Compile and link with -pthread.
// 功能: 等待线程 thread 结束。
// 如果线程 thread 已结束,则立即返回。
// 线程 thread 必须是可等待的。
// 多个线程同时等待同一个线程,结果未定义。
// 如果调用 pthread_join() 的线程被取消,则线程 thread 依然
// 保持可等待。
// 参数: thread 要等待的线程
// retval 结束线程的返回值。如果非 NULL,线程的退出状态会保存
// 在 *retval 中;如果线程 thread 已被取消,则会保存
// PTHREAD_CANCELED 在 *retval 中
// 返回值:成功返回 0,失败返回错误号
6.0 int pthread_cancel(pthread_t thread)见博客
#include <pthread.h>
int pthread_cancel(pthread_t thread);
Compile and link with -pthread.
// 功能: 请求取消线程 thread
// 线程能否及何时取消,取决于线程属性中的 state 和 type,
// pthread_setcancelstate() 函数可使能或禁用,
// pthread_setcanceltype() 函数可设置何时取消(异步和延迟)。
// 执行取消的步骤:
// 1. 按 pthread_cleanup_push(3) 相反的顺序调用清除函数。
// 2. 线程特定的数据自毁装置被调用。
// 3. 线程结束
// 以上取消步骤异步于 pthread_cancel() 函数
// 参数: thread 要取消的线程
// 返回值:成功返回 0,失败返回非0的错误号
7.0 清理线程
void *start_routine(void *arg)
{
int i = 0;
// 入栈和出栈必须成对出现
pthread_cleanup_push(routine1, (void *) 1);
pthread_cleanup_push(routine2, (void *) 2);
pthread_cleanup_push(routine3, (void *) 3);
pthread_cleanup_push(routine4, (void *) 4);
printf("---------------\n");
// 退出时会自动按入栈的相反顺序调用清理函数
//pthread_exit((void *) 1);
// exit(3) 退出时不会自动调用清理函数
//exit(1);
// 取消自己时会自动按入栈的相反顺序调用清理函数
pthread_cancel(pthread_self());
// 手动出栈
pthread_cleanup_pop(1); // 参数 非0 表示出栈并执行
pthread_cleanup_pop(0); // 参数 0 表示只出栈,不执行
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
printf("===============\n");
return NULL;
}
8.0 线程调度
// 初始化默认的线程属性到 attr 中
int pthread_attr_init(pthread_attr_t *attr);
// 销毁 attr 中的线性属性
int pthread_attr_destroy(pthread_attr_t *attr);
Compile and link with -pthread.
// 以上函数成功返回 0,失败返回非 0 的错误号
// 获取/设置线程分离状态
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t *attr,
int *detachstate);
// 状态取值:
// PTHREAD_CREATE_DETACHED 分离的
// PTHREAD_CREATE_JOINABLE 可等待的(默认的)
// 获取/设置竞争调度范围
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
// 调度范围取值:
// PTHREAD_SCOPE_SYSTEM 系统级,Linux 只支持系统级
// PTHREAD_SCOPE_PROCESS 进程级
// 注意,必须使用 pthread_attr_setinheritsched(3) 函数设置继承属性为
// PTHREAD_EXPLICIT_SCHED 才能设置调度范围
// 获取/设置调度策略
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
// 调度策略取值:
// SCHED_FIFO 先进先出调度策略。具有最高优先级的,等待最长时间
// 的线程先调度。实时策略,支持优先级抢占
// SCHED_RR 在FIFO的基础上加入了时间片轮询。实时策略,支持优先级抢占
// SCHED_OTHER 系统默认调度策略,竞争的线程按优先级得到时间片。
// 非实时策略,不支持优先级抢占(默认策略)
// 注意,必须使用 pthread_attr_setinheritsched(3) 函数设置继承属性为
// PTHREAD_EXPLICIT_SCHED 才能设置调度范围
// 获取/设置调度优先级
int pthread_attr_setschedparam(pthread_attr_t *attr,
const struct sched_param *param);
int pthread_attr_getschedparam(const pthread_attr_t *attr,
struct sched_param *param);
struct sched_param {
int sched_priority; /* Scheduling priority */
};
// 优先级数值越大,级别越高
// SCHED_FIFO 和 SCHED_RR 策略下静态优先级为 1 - 99
// 其它策略下优先级为 0
// 注意,必须使用 pthread_attr_setinheritsched(3) 函数设置继承属性为
// PTHREAD_EXPLICIT_SCHED 才能设置调度范围