线程常用api
线程常用api
pthread_create
该api用于创建一个新线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void*(*start_routine)(void *), void *arg)
pthread_t *thread:指向线程标识符的指针,用于存储新创建的线程的线程标识符
const pthread_attr_t *attr:用来设置线程优先级、栈大小等属性,传入NULL时使用默认属性创建线程
void*(*start_routine)(void *):一个指向函数的指针,定义了新线程执行的入口。该函数必须接受一个void*类型的参数,并返回void*类型的结果
void *arg:start_routine函数的参数,可以是一个指向任意类型数据的指针
return:成功返回0,失败返回非0
例:
void *pthread_input(void *arg) {
int i=0;
while(1) {
char c = fgetc(stdin);
if(c && c != '\n') {
buf[i++] = c;
if(i > BUF_LEN) {
i = 0;
}
}
}
}
void *pthread_output(void *arg) {
int i = 0;
while(1) {
if(buf[i]) {
fputc(buf[i],stdout);
buf[i++] = 0;
if (i > BUF_LEN) {
i = 0;
}
}
else {
sleep(1);
}
}
}
pthread_t pid_input,pid_output;
pthread_create(&pid_input,NULL,pthread_input,NULL);
pthread_create(&pid_output,NULL,pthread_output,NULL);
pthread_exit
该api用于关闭调用该方法的线程
void pthread_exit(void *retval)
void *retval:要返回给其他线程的数据
pthread_join
该api用于等待指定线程结束,获取线程返回值并回收它的资源
int pthread_join(pthread_t thread, void **retval)
pthread_t thread:指定线程的线程id
void **retval:这是一个可选参数,用于接受线程结束后传递的返回值。
return:成功返回0,失败返回1
例:
pthread_t pthid;
pthread_create(pthid,NULL,func,NULL);
pthread_join(pthid,NULL);
pthread_detach
该api用于在线程结束后自动回收该线程的资源,无需等待。
int pthread_detach(pthread_t thread)
pthread_t thread:要回收资源的线程id
return:成功返回0,失败返回错误码
例:
pthread_t tid;
pthread_create(tid,NULL,func,NULL);
pthread_detach(tid);
pthread_cancel
该api用于终止指定线程
int pthread_cancel(pthread_t thread)
pthread_t thread:要终止线程的线程id
return:成功返回0,失败返回非0错误码
例:
if (pthread_cancel(tid) != 0){
perror("pthread_cancel");
}
pthread_setcancelstate
该api用于设置调用线程的取消状态
int pthread_setcancelstate(int state, int *oldstate)
int state:要设置的目标状态
int *oldstate:用于返回历史状态
return:成功返回0,失败返回非0错误码
int state目标状态如下:
1、PTHREAD_CANCEL_ENABLE:启用取消功能
2、PTHREAD_CANCEL_DISABLE:禁用取消功能
例:
void *func(void *arg) {
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
//该线程被设置为不可被取消
}
pthread_setcanceltype
该api用于设置调用线程的取消类型
int pthread_setcanceltype(int type, int *oldtype)
int type:要设置的目标类型
int *oldtype:用于返回历史状态
return:成功返回0,失败返回非0错误码
int type目标类型如下:
1、PTHREAD_CANCEL_DEFERRED:设置取消类型为推迟
2、PTHREAD_CANCEL_ASYNCHRONOUS:设置取消类型为异步
推迟意味着取消请求会被挂起,直至被取消线程的执行取消点函数(pthread_testcancel)时才会真正执行线程的取消操作
异步意味着线程可能在任何时候被取消
例:
void *func(void *arg) {
//默认取消类型为推迟,无需设置
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
//该线程的取消类型被设置为异步
}
pthread_mutex_lock
该api用于给被调用的线程设置互斥锁,如果互斥锁已经被其他线程锁定,调用该api的线程将会被阻塞,直到互斥锁变为可用状态。
int pthread_mutex_lock(pthread_mutex_t *mutex)
pthread_mutex_t *mutex:锁
return:成功时返回0,失败是返回错误码
例:
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *func(void *arg) {
pthread_mutex_lock(&mutex);
}
pthread_mutex_trylock
该api用于尝试锁定指定的互斥锁,与pthread_mutex_lock不同,如果互斥锁已经被其他线程锁定,pthread_mutex_trylock不会阻塞调用线程,而是立即返回一个错误码(EBUSY)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_t *mutex:锁
return:成功时返回0,失败是返回错误码
例:
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *func(void *arg) {
pthread_mutex_trylock(&mutex);
}
pthread_mutex_unlock
该api用于解锁指定的互斥锁。调用线程必须是当前持有互斥锁的线程,否则解锁操作可能会失败
int pthread_mutex_unlock(pthread_mutex_t *mutex)
pthread_mutex_t *mutex:锁
return:成功时返回0,失败是返回错误码
例:
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *func(void *arg) {
pthread_mutex_lock(&mutex);
...
pthread_mutex_unlock(&mutex);
}
pthread_rwlock_init
该api用于为 rwlock 指向的读写锁分配所有需要的资源,并将锁初始化为未锁定状态。 读写锁的属性由 attr 参数指定,如果 attr 为 NULL,则使用默认属性。当锁的属性为默认时,可以通过宏 PTHREAD_RWLOCK_INITIALIZER 初始化
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr)
pthread_rwlock_t *restrict rwlock:读写锁
const pthread_rwlockattr_t *restrict attr:读写锁的属性
return:成功返回0,失败返回错误码
restrict关键字表示该对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容
例:
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy
该api用于销毁创建的读写锁,并释放它的所以资源
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁
例:
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);
pthread_rwlock_rdlock
该api用于应用一个读锁到rwlock指向的读写锁上,并使调用线程获得读锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁
return:成功返回0,失败返回错误码
例:
void *func(void *arg) {
pthread_rwlock_rdlock(&rwlock);
}
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);
pthread_rwlock_wrlock
该api用于应用一个写锁到 rwlock 指向的读写锁上,并使调用线程获得写锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁
return:成功返回0,失败返回错误码
例:
void *func(void *arg) {
pthread_rwlock_wrlock(&rwlock);
}
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);
pthread_rwlock_unlock
该api用于释放调用线程锁持有的 rwlock 指向的读写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
pthread_rwlock_t *rwlock:读写锁
return:成功返回0,失败返回错误码
例:
void *func(void *arg) {
pthread_rwlock_rdlock(&rwlock);
pthread_rwlock_unlock(&rwlock);
}
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock,NULL);
pthread_rwlock_destroy(&rwlock);
pthread_rwlockattr_init
该api用于使用所有属性的默认值初始化 attr 指向的属性对象
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
pthread_rwlockattr_t *attr:读写锁属性对象指针
return:成功时返回0,失败时返回错误码
例:
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_destroy
该api用于销毁读写锁属性对象
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
pthread_rwlockattr_t *attr:读写锁属性对象指针
return:成功时返回0,失败时返回错误码
例:
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_destroy(&attr);
pthread_rwlockattr_setkind_np
该api用于将 attr 指向的属性对象中的"锁类型"属性设置为 pref 规定的值
int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref)
pthread_rwlockattr_t *attr:读写锁属性对象指针
int pref:希望设置锁的类型
return:成功时返回0,失败时返回错误码
int pref锁的类型可以被设置为以下三种取值模式中的其中一种:
1、PTHREAD_RWLOCK_PREFER_READER_NP: 默认值,读线程拥有更高优先级。当存在阻塞的写线程时,读线程仍然可以获得读写锁。只要不断有新的读线程,写线程将一直保持" 饥饿"
2、PTHREAD_RWLOCK_PREFER_WRITER_NP: 写线程拥有更高优先级。这一选项被 glibc 忽略
3、PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP: 写线程拥有更高优先级,在 当前系统环境下,它是有效的,将锁类型设置为该值以避免写饥饿
例:
pthread_rwlockattr_t attr;
pthread_rwlock_t rwlock;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE);
pthread_rwlock_init(&rwlock,&attr);
pthread_rwlockattr_destroy(&attr);
pthread_rwlockattr_destroy(&rwlock);
pthread_cond_wait
该api用于阻塞当前线程并临时释放 mutex 锁,并等待其他线程调用 pthread_cond_signal 或 pthread_cond_broadcast 唤醒。被唤醒后该线程会尝试重新获取 mutex 锁。线程在被唤醒时,会从之前的阻塞处继续向下执行
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)
pthread_cond_t *restrict cond:指向条件变量的指针条件变量用于等待某个条件的发生。通过某一cond等待的线程需要通过同一cond的signal唤醒
pthread_mutex_t *restrict mutex:与条件变量配合使用的互斥锁的指针。在调用 pthread_cond_wait之前,线程必须已经获得了这个互斥锁
return:成功时返回0,失败时返回错误码
例:
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *producer(void *arg) {
int item = 1;
while (1) {
pthread_mutex_lock(&mutex);
while(count == BUF_SIZE) {
pthread_cond_wait(&cond,&mutex);
}
buf[count++] = item++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
void *consumer(void *arg) {
while(1) {
pthread_mutex_lock(&mutex);
while(count == 0) {
pthread_cond_wait(&cond,&mutex);
}
printf("%d",buf[--count]);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
/*
该代码的执行流程是:
producer优先获得互斥锁,在获取到锁后向buf中写入数字,每写入5个,就会阻塞并且释放互斥锁。当producer阻塞并释放互斥锁后,consumer便成功获得互斥锁,并开始从buf中写出数据,每写出5个,就会阻塞并且释放互斥锁。当consumer阻塞并释放互斥锁后,producer便成功获得互斥锁。
*/
pthread_cond_timedwait
该api同pthread_cond_wait 相似,但是它添加了超时机制。如果在指定的 abstime 时间内条件变量没有被触发,函数将返回一个超时错误(ETIMEDOUT)
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime)
pthread_cond_t *restrict cond:指向条件变量的指针
pthread_mutex_t *restrict mutex:与条件变量配合使用的互斥锁的指针
const struct timespec *restrict abstime:指向 timespec结构的指针,表示等待条件变量的绝对超时时间。timespec结构包含秒和纳秒两部分,指定了从某一固定点(如 UNIX 纪元,1970年1月1日)开始的时间
return:成功时返回 0;如果超时则返回 ETIMEDOUT;其他错误情况返回相应的错误码
pthread_cond_signal
该api用于唤醒因cond而阻塞的线程,如果有多个因cond阻塞的线程,则随机唤醒一个。如果没有线程在等待,则什么也不做
int pthread_cond_signal(pthread_cond_t *cond)
pthread_cond_t *restrict cond:指向条件变量的指针
return:成功返回0,失败返回错误码
pthread_cond_broadcast
该api用于唤醒所有因cond而阻塞的线程。如果没有线程在等待,则什么也不做
int pthread_cond_broadcast(pthread_cond_t *cond)
pthread_cond_t *restrict cond:指向条件变量的指针
return:成功返回0,失败返回错误码
sem_init
该api用于在sem指向的地址初始化一个无名信号量
int sem_init(sem_t *sem, int pshared, unsigned int value)
sem_t *sem:信号量的地址
int pshared:指明信号量是线程间共享还是进程间共享
unsigned int value:信号量的初始值
return:成功返回0,失败返回EOF
int pshared有两种取值:
1、0:信号量是线程间共享的,应该被置于所有线程均可见的地址(如,全局变量或在堆中动态分配的变量)
2、非0:信号量是在进程间共享的,应该被置于共享内存区域,任何进程只要能访问共享内存区域,即可操作进程间共享的信号量
例:
sem_t unnamedsem;
sem_init(&unnamedsem,0,1);
sem_destroy
该api用于销毁sem指向的无名信号量
int sem_destroy(sem_t *sem)
sem_t *sem:信号量的地址
return:成功返回0,失败返回EOF
例:
sem_t unnamedsem;
sem_init(&unnamedsem,0,1);
sem_destroy(&unnamedsem);
sem_post
该api用于将 sem 指向的信号量加一,如果信号量从 0 变为 1,且其他进程或线程因信号量而阻塞,则阻塞的进程或线程会被唤醒并获取信号量,然后继续执行。POSIX 标准并未 明确定义唤醒策略,具体唤醒的是哪个进程或线程取决于操作系统的调度策略
int sem_post(sem_t *sem)
sem_t *sem:信号量的地址
return:成功返回0,失败返回EOF
例:
void *plusOne(void *argv) {
sem_wait(&unnamed_sem);
int tmp = shard_num + 1;
shard_num = tmp;
sem_post(&unnamed_sem);
}
sem_wait
该api用于将 sem 指向的信号量减一。如果信号量的值大于 0,函数可以执行减一操作, 然后立即返回,调用线程继续执行。如果当前信号量的值是 0,则调用阻塞直至信号量的 值大于 0,或信号处理函数打断当前调用
int sem_wait(sem_t *sem)
sem_t *sem:信号量的地址
return:成功返回0,失败返回EOF
sem_open
该api用于创建或打开一个已经存在的POSIX有名信号量
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value)
const char *name:信号量的名称
int oflag:标记位,控制调用函数的行为。是一个或多个值或操作的结果。常用的是 O_CREAT
mode_t mode:有名信号量在临时文件系统中对应文件的权限。需要注意的是,应确保每个需要访问当前有名信号量的进程都可以获得读写权限
unsigned int value:信号量的初始值
return: 成功则返回创建的有名信号量的地址,失败则返回 SEM_FAILED,同时设置 errno以指出错误原因
例:
char *sem_name = "/named_sem";
sem_t *sem = sem_open(sem_name,O_CREAT,0666,1);
sem_close
该api用于关闭对于sem指向有名信号量的引用
int sem_close(sem_t *sem)
sem_t *sem:有名信号量指针
return:成功返回0,失败返回EOF
例:
char *sem_name = "/named_sem";
sem_t *sem = sem_open(sem_name,O_CREAT,0666,1);
sem_close(sem);
sem_unlink
该api用于移除内存中的有名信号量对象,/dev/shm 下的有名信号量文件会被清除。当 没有任何进程引用该对象时才会执行清除操作。只应该执行一次
int sem_unlink(const char *name)
const char *name:信号量的名称
return:成功返回0,失败返回EOF
g_thread_pool_new
该api用于创建新的线程池
GThreadPool *g_thread_pool_new(GFunc func,gpointer user_data,gint max_threads,gboolean exclusive,GError **error);
GFunc func:线程池中执行的函数
gpointer user_data:传递给func的数据,可以为NULL
gint max_threads:线程池容量,即当前线程池中可以同时运行的线程数。-1表示没有限制
gboolean exclusive:独占标记位。决定当前线程池独占所有的线程还是和其他线程池共享这些线程
GError **error:用于报告错误信息,可以是NULL,表示忽略错误
return:GThreadPool *线程池实例指针。无论是否发生错误,都会返回有效的线程池
gboolean exclusive独占标记位的取值如下:
1、TRUE:立即启动数量为 max_threads 的线程,且启动的线程只能被当前线程池使用
2、FALSE:只有在需要时,即需要执行任务时才创建线程,且线程可以被多个非独享资源的线程池共用
g_thread_pool_push
该api用于向pool指定的线程池实例添加数据
gboolean g_thread_pool_push(GThreadPool *pool,gpointer data,GError **error)
GThreadPool *pool:指向线程池实例的指针
gpointer data:传递给每个任务的独享数据
GError **error:GError **error:用于报告错误信息,可以是NULL,表示忽略错误
return:成功返回true,失败返回false
g_thread_pool_free
该api用于释放pool指向的线程池分配的所有资源
void g_thread_pool_free (GThreadPool* pool,gboolean immediate,gboolean wait_)
GThreadPool *pool:指向线程池实例的指针
gboolean immediate:是否立即释放线程池
gboolean wait_:当前函数是否阻塞等待所以任务完成
gboolean immediate的取值如下:
1、TRUE:立即释放所有资源,未处理的数据不被处理
2、FALSE:在最后一个任务执行完毕之前,线程池不会被释放
需要注意的是:执行任务时,线程池的任何一个线程都不会被打断。无论这个参数是何取值,都可以保证至少线程池释放前正在运行的线程可以完成它们的任务。
gboolean wait_的取值如下:
1、TRUE:所有需要处理的任务执行完毕当前函数才会返回
2、FALSE:当前函数立即返回