线程结束方式
1.pthread_cancel
函数定义结构:
#include <pthread.h>
int pthread_cancel(pthread_t thread);
参数:
thread:类型为pthread_t,表示要取消的线程的标识符。
返回值:
成功时返回0。
失败时返回错误码,可能的错误码包括但不限于EINVAL(表示传入的线程ID无效)和ESRCH(表示没有找到指定的线程)。
2.pthread_detach
函数定义结构:
#include <pthread.h>
int pthread_detach(pthread_t thread);
参数:
thread:类型为pthread_t,表示要设置为分离状态的线程的标识符。
返回值:
成功时返回0。
失败时返回错误码,可能的错误码同样包括但不限于EINVAL(表示传入的线程ID无效)和ESRCH(表示没有找到指定的线程)。
线程的资源回收
1.pthread_join //需要自己回收 ---线程的属性 (可结合性) --- 一般是子线程 在较短时间内运行完
2.pthread_detach //可分离属性 ---子线程运行很久才结束 --- 设置分离属性
线程的资源回收与线程的属性(可结合或分离)密切相关:
- 可结合(joinable)线程:默认情况下,线程是可结合的。这意味着线程在结束时不会自动释放其资源,而是需要由其他线程(通常是主线程)通过调用
pthread_join
函数来显式地结束并回收其资源。pthread_join
函数会阻塞调用它的线程,直到指定的线程结束,并回收该线程的资源。 - 分离(detached)线程:分离线程在结束时会自动释放其资源,而不需要其他线程来调用
pthread_join
。可以通过在创建线程时设置线程属性为PTHREAD_CREATE_DETACHED
,或者在线程内部调用pthread_detach(pthread_self())
来将线程设置为分离状态。设置为分离的线程不能再次被pthread_join
,尝试这样做将返回错误。 - 资源回收
- 可结合性 --- pthread_join //这种用于 ,线程任务较短,主线程需要关心子线程状态
- 可分离性 --- pthread_detach //子程序执行任务较长,主线程也不需要关心子线程状态
对比 线程 和 进程
1.线程 vs 进程
线程 CPU执行的最小单位
进程 资源分配和任务调度基本单位
2. 各自特点 (优缺点)
//1.创建 和 调度
线程
创建速度快
调度速度快
//并发程度 更高
//2. 安全性
线程
好处:
共享了进程的数据空间
共享数据方面 方便
缺点:
安全性不好 //
带来资源竞争 //专门的技术 解决资源竞争 --- 互斥 同步
进程
进程空间相互独立
好处,
安全性好
缺点:
进程间共享数据不方便 //进程间通信 (管道,信号,共享内存)
线程间的资源竞争:
共享资源: 临界资源
临界区 : 访问共享资源(临界资源)那段代码
互斥锁相关函数
互斥锁
互斥 排他性 --- 要么不访问 要访问就是一次完整操作
框架:
定义互斥锁 ==》初始化锁 ==》加锁 ==》解锁 ==》销毁
初始化互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
mutex:指向互斥锁变量的指针。
attr:指向互斥锁属性的指针,如果为NULL,则使用默认属性。
销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex:指向需要销毁的互斥锁变量的指针。
锁定互斥锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
mutex:指向需要锁定的互斥锁变量的指针。
解锁互斥锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
mutex:指向需要解锁的互斥锁变量的指针。
尝试锁定互斥锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
mutex:指向需要尝试锁定的互斥锁变量的指针。
如果互斥锁已被其他线程锁定,pthread_mutex_trylock会立即返回EBUSY错误,而不是阻塞当前线程。
死锁
死锁:在使用互斥锁时,要特别注意避免死锁的情况,即两个或多个线程互相等待对方释放锁。
锁的顺序:在多个锁的场景下,需要保证所有线程都以相同的顺序获取锁,以避免死锁。
性能影响:虽然互斥锁能有效保护共享资源,但它们也可能成为性能瓶颈。过度使用锁或在锁的临界区内执行过多操作都会降低程序的性能。