【Linux】死锁四条件的底层逻辑:从锁冲突到 STL 组件的线程安全实践(Ⅵ)

一、死锁概念

死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用不会释放的资源而处于的一种永久等待状态。

为了方便表述,假设现在线程A,线程B必须同时持有锁1和锁2,才能进行后续资源的访问:

申请一把锁是原子的,但是申请两把锁就不一定了:

造成的结果是:

二、死锁的四个必要条件

互斥条件:一个资源每次只能被一个执行流使用。说人话就是使用了锁。

请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放。

**不剥夺条件:**一个执行流已获得的资源,在末使用完之前,不能强行剥夺。

**循环等待条件:**若干执行流之间形成一种头尾相接的循环等待资源的关系:

三、避免死锁问题

破坏死锁的四个必要条件,例如:不使用锁,破坏互斥条件,在申请锁时,使用:

cpp 复制代码
pthread_mutex_trylock(&mutex)

申请失败不会阻塞在哪里,我们可以使用这个函数去申请锁,如果失败了,让该线程释放锁,进而再申请锁,破坏请求与保持条件;使用:资源一次性分配、使用超时机制、加锁顺序来,破坏循环等待条件,也可以使用C++的 std::lock 函数来破坏循环等待条件,原理是:同时申请多个锁成功才能访问对应的资源;

四、STL、智能指针和线程安全

问题:STL中的容器是否是线程安全的?

答:不是,原因:STL的设计初衷是将性能挖掘到极致,而一旦涉及到加锁保证线程安全,会对性能造成巨大的影响,而且对于不同的容器,加锁方式的不同,性能可能也不同(例如hash表的锁表和锁桶),因此STL默认不是线程安全.如果需要在多线程环境下使用,往往需要调用者自行保证线程安全。

问题:智能指针是否是线程安全的?

答:对于 unique_ptr,由于只是在当前代码块范围内生效,因此不涉及线程安全问题,对于 shared_ptr,多个对象需要共用一个引用计数变量,所以会存在线程安全问题,但是标准库实现的时候考虑到了这个问题,基于原子操作(CAS)的方式保证shared_ptr 能够高效,原子的操作引用计数。


相关推荐
科技小E8 分钟前
模型训完≠能用:深度学习推理工作站DLTM推理验证如何把住“最后一公里”质量关
服务器·深度学习·自动化
纪念 22914 分钟前
C++ list讲解
c++·windows·list
Lsetea15 分钟前
OpenSSL的checkhost显示不匹配却退出0:名称检查与证书验收
linux·https·shell·ssl证书·openssl
张文君26 分钟前
Ubuntu iSCSI CHAP认证与Win11挂载
linux·运维·ubuntu
一直C29 分钟前
嵌入式 Linux 驱动开发学习笔记:中断、等待队列与工作队列
linux·驱动开发·嵌入式硬件·学习·imx6ull
程序员-Benothing36 分钟前
Linux防火墙配置教程:iptables、firewalld、nftables、ufw
linux·运维·服务器
齐鲁大虾1 小时前
如何通过 CUPS Web 界面(http://localhost:631)安装打印机驱动
linux
Black蜡笔小新1 小时前
中央厨房配餐看不见风险高?EasyCVR可视化监管方案设计
运维·安全·easycvr
木雷坞1 小时前
Docker Compose端口映射排查:用port和inspect定位网页访问失败
运维·docker·容器
yunwei371 小时前
eBPF 实例教程:使用内核跟踪点监控 GPU 驱动活动
linux·后端·性能优化