【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 能够高效,原子的操作引用计数。


相关推荐
念恒123067 小时前
继承(下) (Inheritance)
c++
H Journey8 小时前
C++之 CMake、CMakeLists.txt、Makefile
开发语言·c++·makefile·cmake
莫回首�10 小时前
ubuntu 20.04 多网卡配置,遇到问题总结
linux·网络·ubuntu
网络安全许木10 小时前
自学渗透测试第11天(Linux压缩解压与磁盘管理)
linux·网络安全·渗透测试
问简12 小时前
虚拟化对比
服务器
研究点啥好呢12 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
_dindong12 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
航Hang*12 小时前
Windows Server 配置与管理——第3章:文件系统管理
运维·服务器·windows·vmware
沫璃染墨12 小时前
C++ string 从入门到精通:构造、迭代器、容量接口全解析
c语言·开发语言·c++
lifewange13 小时前
Linux ps 进程查看命令详解
linux·运维·服务器