pthread
pthread 线程相关
pthread_create
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
pthread_t *thread //线程id,实际上是一个无符号长整型
const pthread_attr_t *attr //线程属性变量,默认为NULL
void *(*start_routine) (void *) // 线程函数指针(线程运行的函数)线程从这个函数开始独立地运行
void *arg //传递给线程的参数用于函数执行
可以通过attr设置一个新线程的属性, pthread_attr_t 结构体如下
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
struct sched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void * stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
pthread_once
线程的一次性初始化
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次
init_routine()初始化函数
pthread_join
用于等待一个线程结束,并获取其返回值
int pthread_join(pthread_t thread, void **retval);
pthread_t thread: 被连接线程的线程号
void **retval : 指向一个指向被连接线程的返回码的指针的指针
当A线程调用线程B并 pthread_join() 时,A线程会处于阻塞状态,直到B线程结束后,A线程才会继续执行下去
return线程连接的状态,0是成功,非0是失败
pthread_exit
当线程任务运行完成,需要调用该函数将线程退出
void pthread_exit(void *retval);
线程退出的时候,可以返回一个void *类型数值retval。 同样也是返回的一个地址
pthread_detach
可以让主线程和子线程分离
使用pthread_exit或者线程自动结束后,其退出状态不由其他线程获取,而直接自己自动释放
pthread_detach(pthread_t t);
pthread_setname_np pthread_getname_np
设置/获取 名称的线程
#include <pthread.h>
int pthread_setname_np(pthread_t thread, const char *name);
int pthread_getname_np(pthread_t thread,char *name, size_t len);
thread 需要设置/获取 名称的线程
name 要设置/获取 名称的buffer
pthread_self
获得自身线程id
#include <pthread>
pthread_t pthread_self(void);
返回获得自身线程id
pthread_equal
对比两线程id是否相等
#include <pthread>
int pthread_equal(pthread_t tidl , pthread_t tid2);
若相等返回非0,否者返回0
pthread_cancel
请求取消同一进程中的其他线程
#include <pthread>
int pthread_cancel(pthread_t tid);
成功返回0,否则返回错误编号
pthread_cleanup_push pthread_cleanup_pop
pthread_cleanup_push处理程序记录在栈中,也就是说他们的执行顺序与他们注册的顺序相反
#include <pthread.h>
//第一参数:函数,第二个参数:传给函数的数据
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_clean_pop(int execute);
pthread_cleanup_push 的作用是创建栈帧,设置回调函数,该过程相当于入栈。回调函数的执行与否有以下三种情况:
- 线程被取消的时候(pthread_cancel)
- 线程主动退出的时候(pthread_exit)
- pthread_cleanup_pop的参数为非0值(pthread_cleanup_pop)
pthread_cleanup_pop 函数的作用是执行回调函数 或者 销毁栈帧,该过程相当于出栈
-
当 execute = 0 时, 处在栈顶的栈帧会被销毁,pthread_cleanup_push的回调函数不会被执行
-
当 execute != 0 时,pthread_cleanup_push 的回调函数会被执行
pthread 线程同步相关
互斥锁
pthread_mutex_init pthread_mutex_destory
互斥变量使用特定的数据类型:pthread_mutex_t
pthread_mutex_init对互斥量初始化
如果动态分配互斥量,在释放内存前要调用pthread_mutex_destory
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
return 成功0,出错返回错误编号
pthread_mutex_lock pthread_mutex_trylock pthread_mutex_unlock
对互斥量加锁,尝试加锁,解锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_timedlock
该函数允许线程阻塞特定时间,如果加锁失败就会返回ETIMEDOUT
#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timesec *restrict tsptr);
return 成功0,出错返回错误编号
读写锁
当读写锁是写加锁状态时,所有试图对这个锁加锁的线程都会被阻塞
当读写锁是读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是任何希望以写模式对此锁进行加锁的线程都会被阻塞
pthread_rwlock_init pthread_rwlock_destroy
读写锁初始化,释放内存
#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
return 成功0,出错返回错误编号
pthread_rwlock_rdlock pthread_rwlock_wrlock pthread_rwlock_unlock
pthread_rwlock_rdlock加读锁
pthread_rwlock_wrlock加写锁
pthread_rwlock_unlock解锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
return 成功0,出错返回错误编号
pthread_rwlock_tryrdlock pthread_rwlock_trywrlock
写锁原语条件版本
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
return 成功0,出错返回错误编号
pthread_rwlock_timedrdlock pthread_rwlock_timedwrock
带有超时的读写锁加锁函数
#include <pthread.h>
#include <time.h>
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock,const struct timespec *restrict tsptr);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock,const struct timespec *restrict tsptr);
如果时间到期超时时,我们不能获取锁,两个函数返回ETIMEOUT错误
return 成功返回0否则返回错误编号
条件变量
条件变量与互斥量一直使用时,允许线程以无竞争的方式等待特定的条件发生。条件变量是线程可用的另一种同步机制
条件本身是由互斥量保护的。线程在改变条件状态之前必须产生锁住互斥量,其他线程在获得互斥量之前不会到这种改变,因为互斥量必须在锁定以后才能计算条件
pthread_cond_init pthread_cond_destroy
初始化,释放内存
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
return 成功返回0否则返回错误编号
pthread_cond_wait
作用:(1,2为原子操作)
-
阻塞等待条件变量cond
-
释放已掌握的互斥锁(解锁互斥量)相当于ptherad_mutex_unlock(&mutex);
-
当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁pthread_mutex_lock(&mutex);
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timewait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict tsptr);
return 成功返回0否则返回错误编号
pthread_cond_signal pthread_cond_broadcast
解除在某个条件变量上阻塞的线程的阻塞
pthread_cond_broadcast会解除当前所有在某个条件变量上阻塞的线程的阻塞
pthread_cond_signal解除一个某个条件变量上阻塞的线程的阻塞
#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
return 成功返回0否则返回错误编号
自旋锁
与互斥量类似,但它不是通过休眠使进程阻塞,而是在获取锁之前一直处于忙等阻塞状态。当锁被持有的时间较短,而且线程不希望在重新调度上花费太多成本的情况下使用自旋锁
pthread_spin_init
初始化
#include <pthread.h>
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);
pthread_spin_lock pthread_spin_trylock pthread_spin_unlock
加锁解锁
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
屏障
屏障允许每个线程等待,直到所有的合作线程都到达某一点(屏障),然后从该点继续执行工作
它们允许任意线程等待,直到所有线程完成处理工作,而线程不需要退出,所有线程到达屏障后可以接着工作
pthread_barrier_init pthread_barrier_destroy
初始化
#include <pthread.h>
int pthread_barrier_init(pthread_barrier_t *restrict barrier,const pthread_barrierattr_t *restrict attr,unsigned int count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);
count指定允许所有线程继续执行之前,必须到达屏障的线程数目
pthread_barrier_wait
线程已完成工作,准备等待其他所有线程赶上来
#include <pthread.h>
int pthread_barrier_wait(pthread_barrier_t *barrier);