1、基本概念
- 线程:线程是操作系统中的基本执行单元,也是程序执行流的最小单位
- 线程是轻量级的进程(本质上是一个进程,但进程与线程的空间管理方式不同)
- 线程是 CPU 任务调度的最小单元
- 进程是操作系统资源分配的最小单元
2、线程空间
- 线程必须位于进程中,没有进程,线程无法单独存在
- 线程共享文本段、数据段、堆区空间,独享栈区空间
- 一个进程中的线程切换调度任务是,资源开销较小
3、多线程与多进程的对比
场景 | 多进程 | 多线程 |
效率 | 多进程需要切换映射的物理地址,资源开销较大 | 多线程在同一进程空间内切换任务,资源开销较小 |
通信 | 多进程间内存不共享,需要通过进程间通信的方法通信 | 多线程间共享空间,只需要改变共享空间的数据就能完成通信 |
资源竞争 | 多进程之间没有共享空间,不存在资源竞争 | 多线程通过共享空间通信,需保证资源使用的互斥性,防止线程之间的资源竞争 |
安全 | 多进程间空间独立,一个程序崩溃不会影响其他进程,相对较安全 | 多线程间空间共享,一个程序崩溃会影响其他线程运行 |
4、线程的调度与消亡
与进程的调度与消亡保持一致
5、线程的函数接口
1.线程创建接口
pthread_create
原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
功能:
在进程中创建一个线程
参数:
thread:存放线程 ID 的首地址
attr:线程的属性,默认为 NULL
start_routine:线程函数的入口
arg :线程函数的参数
2.线程 ID 获取接口
pthread_self
原型:
pthread_t pthread_self(void);
功能:
获得调用该函数的线程的ID号
3.线程退出接口
pthread_exit
原型:
void pthread_exit(void *retval);
功能:
结束当前线程任务
参数:
retval:线程结束的值
4.回收线程接口
pthread_join
原型:
int pthread_join(pthread_t thread, void **retval);
功能:
回收线程空间
参数:
thread:要回收的线程的ID
retval:存放线程结束状态空间的首地址
返回值: 成功返回0 失败返回错误码
6、线程属性
1.概念:
- 加入属性:线程结束后需要通过 pthread_join 手动回收线程空间
- 分离属性:线程结束后程序自动回收线程空间
2.相关函数接口
初始化函数接口:pthread_attr_init
原型:
int pthread_attr_init(pthread_attr_t *attr);
功能:
线程属性初始化
参数:
attr:初始化线程首地址
属性设置接口:pthread_attr_setdetachstate
原型:
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
功能:
设置线程属性
参数:
attr :线程属性空间首地址
detachstate:属性设置
PTHREAD_CREATE_DETACHED:分离属性
PTHREAD_CREATE_JOINABLE:加入属性
销毁线程属性对象接口:pthread_attr_destroy
原型:
- int pthread_attr_destroy(pthread_attr_t *attr);
功能:
线程属性销毁
参数:
attr:线程属性空间首地址
7、线程间通信
- 采用全局变量实现进程间通信
- 多线程同时操作会引发资源竞争,需加上互斥锁解决资源竞争问题
8、互斥锁
1.概念与特点
- 解决资源竞争的一种方式也可以看成是一种资源
- 只能加锁一次,在加锁期间不能再次加锁,也不能羌之战有一个加锁的资源,必须等待资源释放(解锁后操作)
- 只能防止线程之间的资源竞争,不能改变代码的先后执行顺序
2.使用方式
- 定义互斥锁(全局变量)并对锁初始化
- 操作全局资源前先加锁,如果加锁成功则完成对全局资源操作
- 如果加锁失败则表示有人占用资源,必须等待其余人释放锁资源才能加锁成功
3.相关函数接口
互斥锁初始化函数
pthread_mutex_init
原型:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
功能:
初始化互斥锁
参数:
mutex:互斥锁空间首地址
attr:互斥锁属性,默认为 NULL
返回值:
成功0,失败-1
互斥锁加锁与开锁与销毁
pthread_mutex_lock / pthread_mutex_unlock /pthread_mutex_destroy
加锁函数:
原型:
int pthread_mutex_lock(pthread_mutex_t *mutex);
开锁函数:
原型:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
销毁函数:
原型:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
9、死锁
1.概念
两个或两个以上的线程(或进程)在执行过程中,由于竞争资源或彼此通信而造成的一种互相等待的现象
2.死锁的特点
- 没有外部干预时,这种等待状态将永久持续
- 每个线程/进程都在等待其他线程/进程释放资源
3.死锁的产生条件
- 互斥条件:资源一次只能被一个线程占用(若资源可以被共享访问,则不会产生死锁)
- 占有并等待:线程至少占有一个资源的同时又等待获取其他线程的资源
- 不可剥夺:已经分配给现成的资源不能被其他线程强行夺取
- 循环等待:存在一个线程等待环路
10、信号量
1.概念
- 信号量是一种用于多线程/多进程环境下控制共享资源访问的同步机制
- 信号量只能完成初始化、销毁、申请、释放四种操作
2.函数接口
初始化函数:sem_init
原型:
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:
初始化信号量
参数:
sem:信号空间首地址
pshared:进程共享开关
0:一个进程间的多个线程共享
非0:多个进程间共享
value:初始化资源的值
如哦资源职位0,申请资源会阻塞等待,直到占用资源的任务释放资源,资源部为 0 才能申请到资源并向下执行
返回值:
成功 0,失败 -1
销毁信号量函数:sem_destroy
原型:
int sem_destroy(sem_t *sem);
功能:
销毁信号量
返回值:
成功 0,失败 -1
信号量申请函数:sem_wait
- 申请信号量会让信号量资源数 -1
- 若信号量资源数为 0,会阻塞等待直到有任务释放资源
原型:
int sem_wait(sem_t *sem);
功能:
申请信号量
参数:
sem:信号量空间首地址
返回值:
成功返回0 失败返回-1
信号量释放函数:sem_post
- 信号量释放后 信号量资源 +1
原型:
int sem_post(sem_t *sem);
功能:
释放信号量
参数:
sem:信号量空间首地址
返回值:
成功返回0 失败返回-1
评论前必须登录!
注册