线程
定义
允许应用程序并发执行的一种机制,共享一份全局内存区
LMP轻量级进程
查看
ps -Lf pid
与进程程区别
线程:代价小,速度快,共享(全局,堆中)数据->内核,
main函数创建的线程叫主线程,其它叫子线程
函数
多行注释
ctrl + shift + /
ctrl + /
创建线程:
#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, 线程库的名字叫pthread, 全名: libpthread.so libptread.a
-
参数:
thread: 传出参数,是pthread_t类型,线程创建成功,会将线程 ID 写入到这个指针指向的内存中 attr: 线程的属性,一般情况下使用默认属性即可,写 NULL start_routine: 函数指针,创建出的子线程的处理动作,也就是该函数在子线程执行, 一般为线程执行函数的函数名即可 arg: 作为实参传递到 start_routine 指针指向的函数内部,多个参数时创建结构体,传入 结构体指针 -
返回值:线程创建成功返回 0,创建失败返回对应的错误号
线程退出:调用该函数当前线程就马上退出了,并且不会影响到其他线程的正常运行
void pthread_exit(void *retval);
pthread_exit(NULL);
线程回收:这个函数是一个阻塞函数,阻塞当前线程,等到要回收的线程执行完毕,回收资源
int pthread_join(pthread_t thread, void **retval);
-
参数:
thread: 要被回收的子线程的线程 IDretval: 二级指针,指向一级指针的地址,是一个传出参数,这个地址中存储了 pthread_exit () 传递出的数据,如果不需要这个参数,可以指定为 NULL -
返回值:线程回收成功返回 0,回收失败返回错误号
线程比较:也可以直接用=,因为pthread_t本质是unsigned long类型
int pthread_equal(pthread_t t1, pthread_t t2);
- 参数:t1 和 t2 是要比较的线程的线程 ID
- 返回值:如果两个线程 ID 相等返回非 0 值,如果不相等返回 0
线程分离:子线程与主线程分离,执行完毕后由操作系统回收资源
int pthread_detach(pthread_t thread);
线程取消:在线程A中杀死线程B,A调用后,B进行了一次系统调用才会被杀死,否则B一直运行
int pthread_cancel(pthread_t thread);
创建条件变量
#include <pthread.h>
pthread_cond_t cond;
线程属性
// 初始化
int pthread_attr_init(pthread_attr_t *attr);
//释放线程属性资源
int pthread_attr_destroy(pthread_attr_t *attr);
//线程分离的状态属性
int pthread_attr_getdetachstate(pthread_attr_t *attr,int detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);
创建互斥锁:一个临界资源对应一把互斥锁,创建为全局变量,因为需要被多个线程函数访问
pthread_mutex_t mutex;
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
化互斥锁
// 初始化互斥锁
// restrict: 是一个关键字, 用来修饰指针, 只有这个关键字修饰的指针可以访问指向的内存地址, 其他指针是不行的
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
上锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
尝试上锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
销毁互斥锁:一般在主线程结束的时候销毁互斥锁
// 释放互斥锁资源
int pthread_mutex_destroy(pthread_mutex_t *mutex);
条件变量
严格意义上来说,条件变量的主要作用不是处理线程同步,而是进行线程的阻塞。如果在多线程程序中只使用条件变量无法实现线程的同步,必须要配合互斥锁来使用。虽然条件变量和互斥锁都能阻塞线程,但是二者是有区别的:
如果一个线程抢到互斥锁并加锁成功,其他线程都会被阻塞,无法访问临界资源
条件变量是在满足一定的条件下阻塞当前线程,如果条件不满足了,所有线程都可以进入临界区访问临界资源,这种情况下还是会导致数据混乱。
创建条件变量
#include <pthread.h>
pthread_cond_t cond;
初始化条件变量
// 初始化
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
参数:
cond: 条件变量的地址
attr: 条件变量属性,一般使用默认属性,指定为 NULL
唤醒阻塞的线程
// 唤醒阻塞在条件变量上的线程, 至少有一个被解除阻塞
int pthread_cond_signal(pthread_cond_t *cond);
// 唤醒阻塞在条件变量上的线程, 被阻塞的线程全部解除阻塞
int pthread_cond_broadcast(pthread_cond_t *cond);
// 销毁释放资源
int pthread_cond_destroy(pthread_cond_t *cond);
信号量
创建信号量
#include <semaphore.h>
sem_t sem;
初始化信号量
// 初始化信号量/信号灯
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
sem:信号量变量地址
pshared: 0:线程同步 非 0:进程同步
value:初始化当前信号量拥有的资源数(>=0),如果资源数为 0,线程就会被阻塞了
消耗信号量
// 函数被调用sem中的资源就会被消耗1个, 资源数-1
int sem_wait(sem_t *sem);
//不会阻塞
int sem_trywait(sem_t *sem);
//阻塞一定时长,时间结构见pthread_cond_timedwait
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
增加信号量
// 调用该函数给sem中的资源数+1
int sem_post(sem_t *sem);
查看信号量的值
// sval是一个传出参数
int sem_getvalue(sem_t *sem, int *sval);
销毁信号量
int sem_destroy(sem_t *sem);
本文来自博客园,作者:InsiApple,转载请注明原文链接:https://www.cnblogs.com/InsiApple/p/16028354.html

浙公网安备 33010602011771号