基本概念
-
线程是轻量级的进程(LWP:Light Weight Process),在 Linux 环境下线程的本质仍是进程。
-
NPTL:Native POSIX Thread Library,是 Linux 线程的一个新实现。
-
线程属性类型 pthread_attr_t
-
一般情况下,main函数所在的线程我们称之为主线程(main线程),其余创建的线程称之为子线程。
线程系统调用
-
创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)-
thread:传出参数,线程创建成功后,子线程的线程ID被写到该变量中。 -
attr: 设置线程的属性,一般使用默认值,NULL -
start_routine: 函数指针,这个函数是子线程需要处理的逻辑代码 -
arg: 给第三个参数使用,传参
-
-
获取线程ID
pthread_t pthread_self(void);
-
比较两个线程ID是否相等
int pthread_equal(pthread_t t1, pthread_t t2);- 不同的操作系统,pthread_t 类型的实现不一样,有的是无符号的长整型,有的是使用结构体去实现的。
-
终止线程
void pthread_exit(void *retval)
-
回收子线程
int pthread_join(pthread_t thread, void **retval);- 回收子线程的资源
- 这个函数是阻塞函数
- 调用一次只能回收一个子线程
- 一般在主线程中使用
-
分离一个线程
int pthread_detach(pthread_t thread);
-
线程取消(终止)
int pthread_cancel(pthread_t thread);- 取消某个线程,可以终止某个线程的运行,但是并不是立马终止,而是当子线程执行到一个取消点,线程才会终止。
- 取消点:系统规定好的一些系统调用,我们可以粗略的理解为从用户区到内核区的切换,这个位置称之为取消点。
-
初始化线程属性变量
int pthread_attr_init(pthread_attr_t *attr);
-
释放线程属性的资源
int pthread_attr_destroy(pthread_attr_t *attr);
-
获取线程分离的状态属性
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
-
设置线程分离的状态属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, intdetachstate);
线程同步
互斥量
- 互斥量 mutex
- 互斥量的类型 pthread_mutex_t
- 两种状态
- 已锁定(locked)
- 未锁定(unlocked)
互斥量系统调用
-
初始化互斥量
-
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr) -
mutex : 需要初始化的互斥量变量
-
attr : 互斥量相关的属性,一般可以传递NULL
- restrict : C语言的修饰符,被修饰的指针,不能由另外的一个指针进行操作。
-
-
释放互斥量的资源
int pthread_mutex_destroy(pthread_mutex_t *mutex)
-
加锁:阻塞
-
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_rwlock_t - 允许多个读出,但只允许一个写入
- 特点:
- 如果有其它线程读数据,则允许其它线程执行读操作,但不允许写操作。
- 如果有其它线程写数据,则其它线程都不允许读、写操作。
- 写是独占的,写的优先级高。
读写锁系统调用
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr)int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
条件变量
- 不是锁,与互斥锁搭配使用。
- 当条件满足时,阻塞/解除阻塞线程。
- 条件变量的类型 pthread_cond_t
条件变量系统调用
-
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr) -
int pthread_cond_destroy(pthread_cond_t *cond) -
等待,调用了该函数,线程会阻塞
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)- 当这个函数调用阻塞的时候,会对互斥锁进行解锁,当不阻塞的,继续向下执行,会重新加锁。
-
等待多长时间,调用了这个函数,线程会阻塞,直到指定的时间结束(不阻塞了)
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime)
-
唤醒一个或者多个等待的线程
int pthread_cond_signal(pthread_cond_t *cond)
-
唤醒所有的等待的线程
int pthread_cond_broadcast(pthread_cond_t *cond)
信号量
- 信号量的类型 sem_t
信号量系统调用
- 初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value)sem: 信号量变量的地址pshared: 0 用在线程间 ,非0 用在进程间value: 信号量中的值
- 释放资源
int sem_destroy(sem_t *sem)
- 对信号量加锁,调用一次对信号量的值-1;如果值为0,就阻塞
int sem_wait(sem_t *sem)
- 对信号量解锁,调用一次对信号量的值+1
int sem_post(sem_t *sem)
int sem_getvalue(sem_t *sem, int *sval)int sem_trywait(sem_t *sem)int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)