一、介绍
线程作为系统执行的最小单位,同一个进程之间的不同线程仅存在私有栈区,除此之外全部共享。
二、线程函数介绍
头文件
#include <pthread.h>
在编译时需要链接动态库 gcc main.c -o app -lpthread
1、创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
返回值:
成功:0
失败:返回错误号
参数:
thread:创建线程的线程号
attr:线程属性,NULL为默认属性
start_routine:线程的执行函数
arg:执行函数的参数
2、查看当前线程号
pthread_t pthread_self(void);
返回值:
成功:当前线程号
不会失败
3、线程退出
1、自行退出,自杀
void pthread_exit(void *retval);
参数:
retval:线程退出的遗言
2、强制退出,他杀
int pthread_cancel(pthread_t thread);
返回值:
成功:0
失败:-1
参数:
thread:需要退出的线程号
4、线程回收
int pthread_join(pthread_t thread, void **retval);
返回值:
成功:0
失败:-1
参数:
thread:要回收的线程号
retval:由ptread_exit函数传递的值
三、线程控制函数
线程控制为:互斥和同步
互斥:对临界资源无差别的排他性访问
同步:对临界资源按照一定顺序访问
条件变量:根据信号随机唤醒一个线程持有
1、互斥函数
头文件<pthread.h>
1、初始化
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
返回值:
成功:0
失败:非零
参数:
mutex:要初始化的互斥锁
attr:要初始化的值,NULL表示默认锁
2、加锁,阻塞等待
int pthread_mutex_lock(pthread_mutex_t *mutex);
返回值:
成功:0
失败:非零
参数:
mutex:互斥锁
3、解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:
成功:0
失败:非零
参数:
mutex:互斥锁
4、销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
返回值:
成功:0
失败:非零
参数:
mutex:互斥锁
5、trylock,尝试加锁,当锁未被释放立即返回
int pthread_mutex_trylock(pthread_mutex_t *mutex);
返回值:
成功:0
失败:非零,E_AGAIN
参数:
mutex:互斥锁
2、同步函数(信号量)
头文件<semaphore.h>
1、无名信号初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);
返回值:
成功:0
失败:-1
参数:
sem:信号量
pshared:
0:线程间使用
!0:进程间使用
value:初始化值
0:阻塞
1:释放,可以执行
2、无名信号销毁信号量
int sem_destroy(sem_t *sem);
返回值:
成功:0
失败:-1
参数:
sem:信号量
3、等待信号, sem=sem-1
int sem_wait(sem_t *sem);
返回值:
成功:0
失败:-1
参数:
sem:信号量
4、释放信号量,sem=sem+1
int sem_post(sem_t *sem);
返回值:
成功:0
失败:-1
参数:
sem:信号量
5、超时等待
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
返回值:
成功:0
失败:-1
参数:
sem:信号量
abs_timeout:超时时间
struct timespec {undefined
time_t tv_sec; // seconds
long tv_nsec; // and nanoseconds
};
clock_gettime(CLOCK_REALTIME, &ts); 获取当前时间
abs_timeout.sec+=value; 重新填充时间
6、有名信号量打开
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
返回值:
成功:返回信号量地址
失败:SEM_FAILED
参数:
name:信号量名称
oflag:
O_CREAT:如果不存在就创建
O_CREAT|O_EXCL:如果名称为输入名称的信号量已存在则返回失败
mode:创建信号量的权限,建议0664
value:创建时信号量的初始值,如果已存在则则忽略
7、有名信号量关闭 (关闭并未从系统删除,需要使用unlink从系统删除)
int sem_close(sem_t *sem);
返回值:
成功:0
失败:-1
参数:
sem:信号量的地址
8、有名信号量删除
int sem_unlink(const char *name);
返回值:
成功:0
失败:-1
参数:
name:需要删除信号量的名称
3、条件变量
头文件<pthread.h>
1、初始化
静态初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
动态初始化
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
返回值:
成功:0
失败:非零
参数:
cond:变量
attr:通常为NULL
2、销毁
int pthread_cond_destroy(pthread_cond_t *cond);
返回值:
成功:0
失败:非零
参数:
cond:变量
3、等待
(1)有超时
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
返回值:
成功:0
失败:非零
参数:
cond:变量
mutex:互斥锁
abstime:超时时间
struct timespec {undefined
time_t tv_sec; // seconds
long tv_nsec; // and nanoseconds
};
clock_gettime(CLOCK_REALTIME, &ts); 获取当前时间
abs_timeout.sec+=value; 重新填充时间
(2)阻塞等待
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
返回值:
成功:0
失败:非零
参数:
cond:变量
mutex:互斥锁
使用流程:
(1)pthread_mutex_lock()上锁,
(2)pthread_cond_wait()等待,等待过程分解为为:解锁--条件满足--加锁
(3)pthread_mutex_unlock()解锁。
4、激活
(1)激活一个
int pthread_cond_signal(pthread_cond_t *cond);
返回值:
成功:0
失败:非零
参数:
cond:变量
(2)全部激活
int pthread_cond_broadcast(pthread_cond_t *cond);
返回值:
成功:0
失败:非零
参数:
cond:变量
4、自旋锁
1、初始化锁
int pthread_spin_init(pthread_spinlock_t* lock,int pshared);
返回值:
成功:0
失败:非零
参数:
lock:自旋锁
pshared:
PTHREAD_PROCESS_SHARED:任意进程可访问
PTHREAD_PROCESS_PRIVATE:单一进程的线程间访问
2、销毁锁
int pthread_spin_destorya(pthread_spinlock_t* lock);
返回值:
成功:0
失败:非零
参数:
lock:自旋锁
3、阻塞加锁
int pthread_spin_lock(pthread_spinlock_t* lock);
返回值:
成功:0
失败:非零
EDEADLK:死锁
EBUSY:持有失败
参数:
lock:自旋锁
4、非阻塞加锁
int pthread_spin_trylock(pthread_spinlock_t* lock);
返回值:
成功:0
失败:非零
EDEADLK:死锁
EBUSY:持有失败
参数:
lock:自旋锁
5、解锁
int pthread_spin_unlock(pthread_spinlock_t* lock);
返回值:
成功:0
失败:非零
参数:
lock:自旋锁
5、读写锁
1、初始化
(1)动态初始化
int pthread_rwlock_init(pthread_rwlock_t* rwlock);
返回值:
成功:0
失败:非零
参数:
rwlock:读写锁
(2)静态初始化
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
2、申请读锁
int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock);
返回值:
成功:0
失败:非零
参数:
rwlock:读写锁
2、尝试申请读锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock);
返回值:
成功:0
失败:非零
参数:
rwlock:读写锁
3、申请写锁
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock);
返回值:
成功:0
失败:非零
参数:
rwlock:读写锁
4、尝试申请写锁
int pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock);
返回值:
成功:0
失败:非零
参数:
rwlock:读写锁
5、解锁
int pthread_rwlock_unlock(pthread_rwlock_t* rwlock);
返回值:
成功:0
失败:非零
参数:
rwlock:读写锁
6、销毁锁
int pthread_rwlock_destroy(pthread_rwlock_t* rwlock);
返回值:
成功:0
失败:非零
参数:
rwlock:读写锁