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


相关推荐
坚定学代码17 分钟前
基于观察者模式的ISO C++信号槽实现
开发语言·c++·观察者模式·ai
江湖有缘23 分钟前
Jump个人仪表盘Docker化部署教程:从0到 搭建专属导航页
运维·docker·容器
小猪佩奇TONY28 分钟前
Linux 内核学习(14) --- linux x86-32 虚拟地址空间
linux·学习
Lam㊣38 分钟前
Centos 7 系统docker:更换镜像源
linux·docker·centos
FL16238631291 小时前
win11+WSL+Ubuntu-xrdp+远程桌面闪退+黑屏闪退解决
linux·运维·ubuntu
石头5301 小时前
Kubernetes监控全栈解决方案:从零搭建Prometheus+Grafana监控体系
linux
ha20428941941 小时前
Linux操作系统学习记录之---TcpSocket
linux·网络·c++·学习
AOwhisky1 小时前
Linux逻辑卷管理:从“固定隔间”到“弹性存储池”的智慧
linux·运维·服务器
翼龙云_cloud2 小时前
阿里云渠道商:如何使用弹性伸缩来实现计算资源的弹性配置?
服务器·阿里云·云计算
05大叔2 小时前
大事件Day02
运维·服务器