Linux应用软件编程:线程分离属性 互斥机制 同步机制 死锁

7. 线程的分离属性

分离属性 :不需要被其他线程回收的线程,称为具有分离属性的线程,结束时可以被操作系统回收。

非分离属性:可以被其他线程回收或者结束的线程,称为非分离属性的线程 ,结束后必须被其他线程回收

默认属性:非分离属性

设置线程分离属性:

int pthread_detach(pthread_t thread);

功能:设置线程的分离属性

参数:

thread:要设置的线程的线程ID

返回值:

成功:0

失败:非0

8. 线程的互斥机制

多线程访问临界资源时,存在资源竞争问题。

临界资源:多个线程可以同时操作的资源,比如:全局变量,全局队列、共享内存等。

临界区:访问临界资源的代码

如何解决资源竞争问题:

线程的互斥机制:让多个线程在访问临界资源时,具有排他性访问的特性

互斥机制:互斥锁、信号量、读写锁(写独占,读共享)、自旋锁

互斥锁:实现互斥机制

  • 创建互斥锁:pthread_mutex_t

  • 初始化锁:pthread_mutex_init

  • 加锁:pthread_mutex_lock/pthread_mutex_trylock

  • 解锁:pthread_mutex_unlock

  • 销毁锁:pthread_mutex_destroy

    int pthread_mutex_init(pthread_mutex_t *restrict mutex,
    const pthread_mutexattr_t *restrict attr);

功能:初始化互斥锁

参数:

mutex :互斥锁对象地址

attr: 锁的属性地址,默认NULL

返回值:

成功:0

失败:非0

复制代码
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); 

功能:销毁锁

其他锁:

读写锁:读共享,写独占

自旋锁:申请不到锁时,一直占用CPU

9. 线程间同步机制

线程间同步:让多个线程任务执行某部分任务的时候具有先后顺序。

同步方式:信号量

可以将信号量看成一个资源数,当该资源数>0的时候,可以申请到信号量,当资源为0时,申请信号量阻塞等待。申请完信号量时,该信号量对应的资源数自动‑1。释放对应的信号量时,该信号量对应的资源数自动+1。

1.创建信号量:sem_t

2.初始化信号量:

复制代码
int sem_init(sem_t *sem, int pshared, unsigned int value); 

功能:初始化信号量

参数:

sem:初始化的信号量对象地址

pshared:进程间共享还是线程间

0: 线程间

非0:进程间

value:初始化的资源数

返回值:

成功:0

失败:非0

3.申请信号量(P操作):

复制代码
int sem_wait(sem_t *sem); 
int sem_trywait(sem_t *sem); 

4.释放信号量(V操作)

复制代码
int sem_post(sem_t *sem); 

5.销毁信号量

复制代码
int sem_destroy(sem_t *sem);

10. 死锁

死锁:死锁指的是在多线程环境中,每个执行流(线程)都有未释放的资源,且互相请求对方未释放资源,从而导致陷入永久等待状态的情况。

现象:

现象1:忘记释放锁

现象2:重复加锁

现象3:多线程多锁,抢占锁资源不当

如:线程A获取了1锁,线程B获取了2锁,同时线程A还想获取2锁,线程B还想获取1锁

产生死锁的四个必要条件(四条全中 = 死锁,破掉任意一条 = 解除):

(1) 互斥条件:一个资源同一时刻只能被一个任务占用(一个执行流获取锁后,其它执行流不能再获取该锁)。

(2) 请求与保持条件:已经拿着一部分资源不释放,同时又去申请新的资源(执行流本身使用着一把锁并不释放,还在请求别的锁)。

(3) 不剥夺条件:资源只能由持有者主动释放,系统/其他任务不能强行抢过来(A执行流拿着锁,其它执行流不能释放)。

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系(多个执行流拿着对方想要的锁,并且各执行流还去请求对方的锁)。

解决方法:

1.锁一定要成对出现

2.使线程的加解锁顺序一致

3.破坏环路等待条件

使用非阻塞锁,一旦线程发现请求的锁被使用,就去释放自己拥有的资源

复制代码
int pthread_mutex_trylock(pthread_mutex_t *mutex); 
int sem_trywait(sem_t *sem); 
相关推荐
Ruiery8 小时前
Linux 6.6内核内存管理深度解析(十六):mmap — 用户态“申请内存“的真相
linux·运维·服务器
第九序言T8 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
欧米欧9 小时前
Linux系统篇(七),环境变量的底层溯源,核心获取机制与安全应用
linux·运维·服务器
Ruiery9 小时前
Linux 6.6内核内存管理深度解析(十八):KASLR 内核地址空间随机化
linux·运维·服务器·安全
ZhengEnCi10 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
qetfw10 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
龙亘川10 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
程序喵大人10 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
秋天的怀念_David10 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Raas10010 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品