MST

星途 面试题库

面试题:C++多线程同步中死锁的检测与避免

在C++多线程编程中,假设存在多个线程竞争多个资源,有可能产生死锁。请描述死锁产生的四个必要条件,并阐述如何检测死锁以及如何在代码层面避免死锁。
17.2万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

死锁产生的四个必要条件

  1. 互斥条件:资源在同一时刻只能被一个线程占用。例如,打印机资源在某一时刻只能被一个打印任务(线程)使用。
  2. 占有并等待条件:一个线程已经持有了至少一个资源,但又请求新的资源,且在等待新资源分配的过程中,不释放已持有的资源。比如线程A持有资源R1,又请求资源R2,在等待R2的过程中,不释放R1。
  3. 不可剥夺条件:线程已获得的资源,在未使用完之前,不能被其他线程强行剥夺,只能由该线程自己释放。例如线程B获得了数据库连接资源,在它使用完该连接之前,其他线程不能强行夺走这个连接。
  4. 循环等待条件:存在一个线程集合{T1, T2, …, Tn},其中T1等待T2持有的资源,T2等待T3持有的资源,…,Tn等待T1持有的资源,形成一个循环等待链。

死锁检测

  1. 资源分配图算法:通过构建资源分配图,图中节点表示线程和资源,边表示资源的请求和分配关系。使用算法(如深度优先搜索)检查图中是否存在环,若存在环则表示可能存在死锁。
  2. 超时检测:为每个线程的资源请求设置一个超时时间,如果线程在规定时间内未能获取到所需资源,则认为可能发生死锁,并采取相应措施,如终止相关线程。

代码层面避免死锁

  1. 资源分配顺序:对所有资源进行编号,所有线程按照相同的顺序请求资源。例如,线程A和线程B都先请求资源R1,再请求资源R2,这样可以避免循环等待。
  2. 资源一次性分配:线程在启动时一次性请求它所需要的所有资源,而不是逐步请求。如果一次性无法分配所有资源,则该线程不占用任何资源,这样可以避免占有并等待的情况。
  3. 使用超时机制:如上述检测方法中的超时检测,在代码中为资源请求设置超时。若超时未获取到资源,线程释放已持有的资源并重新尝试。
  4. 引入资源分配器:创建一个资源分配器对象,负责管理资源的分配和回收。线程向资源分配器请求资源,资源分配器通过合理的调度算法避免死锁。