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


相关推荐
十日十行13 小时前
Linux和window共享文件夹
linux
端平入洛16 小时前
delete又未完全delete
c++
Sinclair17 小时前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
木心月转码ing21 小时前
WSL+Cpp开发环境配置
linux
端平入洛2 天前
auto有时不auto
c++
Rockbean2 天前
用40行代码搭建自己的无服务器OCR
服务器·python·deepseek
蝎子莱莱爱打怪2 天前
Centos7中一键安装K8s集群以及Rancher安装记录
运维·后端·kubernetes
茶杯梦轩2 天前
CompletableFuture 在 项目实战 中 创建异步任务 的核心优势及使用场景
服务器·后端·面试
崔小汤呀2 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
何中应2 天前
vi编辑器使用
linux·后端·操作系统