MST

星途 面试题库

面试题:C语言多线程中的死锁预防与排查

在一个使用C语言进行多线程编程的项目中,出现了死锁现象。已知有多个线程,它们分别对多个资源进行加锁操作。请描述死锁产生的四个必要条件,并说明如何预防死锁。如果死锁已经发生,你会采取哪些策略和工具来排查死锁问题?
29.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

死锁产生的四个必要条件

  1. 互斥条件:资源在某一时刻只能被一个线程占用。
  2. 占有并等待条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不可剥夺条件:线程已获得的资源,在未使用完之前,不能被其他线程强行剥夺,只能由该线程自己释放。
  4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

预防死锁的方法

  1. 破坏互斥条件:尽量使用可共享的资源,避免独占资源。但有些资源本身特性决定其只能互斥访问,此方法应用场景有限。
  2. 破坏占有并等待条件:在进程开始运行前,一次性分配它所需要的所有资源;或者在申请新资源时,先释放已占有的资源。
  3. 破坏不可剥夺条件:当一个线程占有某些资源又申请新资源得不到满足时,必须释放已经占有的资源,待以后需要时再重新申请。
  4. 破坏循环等待条件:对资源进行编号,规定线程申请资源时必须按照编号从小到大的顺序申请,这样可以避免循环等待。

死锁排查策略与工具

  1. 策略
    • 日志分析:在关键的加锁和解锁位置添加日志,记录线程ID、资源ID以及加锁解锁时间等信息,通过分析日志找出死锁发生的线索。
    • 资源分配图算法:构建资源分配图,通过算法检测图中是否存在环路,若存在环路则可能存在死锁。
  2. 工具
    • pthread库自带工具:在Linux下,使用pthread_mutexattr_settype设置互斥锁类型为PTHREAD_MUTEX_ERRORCHECK,这样当线程试图重复锁定同一互斥锁时,会返回错误,有助于发现死锁。
    • GDB调试:使用GDB的info threads查看所有线程状态,thread <thread_id>切换到指定线程,bt查看线程堆栈信息,通过分析线程堆栈找到死锁相关代码。
    • Valgrind:它能检测出许多内存相关问题,也可用于发现死锁。运行程序时,Valgrind会报告死锁相关信息。