多线程编程之线程死锁问题

拙园 拙园     2022-10-04     507

关键词:

在多线程编程中,除了要解决数据访问的同步与互斥之外,还需要解决的重要问题就是多线程的死锁问题。所谓死锁: 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去。

一、死锁原因与形成条件

  死锁形成的原因:

  1. 系统资源不足
  2. 进程(线程)推进的顺序不恰当;
  3. 资源分配不当

  死锁形成的条件:

  1. 互斥条件:所谓互斥就是进程在某一时间内独占资源。
  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

  从编程经验上来讲,形成死锁的一般原因有以下几种:

  1. 个人使用锁的经验差异。
  2. 程序模块使用锁的差异。
  3. 工程代码版本之间的差异。
  4. 工程代码分支之间的差异。
  5. 修改代码和重构代码带来的差异。

二、常见死锁形成的场景

  死锁形成的常见情况有以下几种:

2.1 忘记释放锁

技术分享图片
void data_process()
{
    EnterCriticalSection();

    if(/* error happens, forget LeaveCriticalSection */)
        return;

    LeaveCriticalSection();
}
技术分享图片

 2.2 单线程重复申请锁

技术分享图片
void sub_func()
{
    EnterCriticalSection();
    do_something();
    LeaveCriticalSection();
}

void data_process()
{
    EnterCriticalSection();
    sub_func();
    LeaveCriticalSection();
}
技术分享图片

 2.3 多线程多锁申请

技术分享图片
void data_process1()
{
    EnterCriticalSection(&cs1);  // 申请锁的顺序有依赖
    EnterCriticalSection(&cs2);
    do_something1();
    LeaveCriticalSection(&cs2);
    LeaveCriticalSection(&cs1);
}

void data_process2()
{
    EnterCriticalSection(&cs2);  // 申请锁的顺序有依赖
    EnterCriticalSection(&cs1);
    do_something2();
    LeaveCriticalSection(&cs1);
    LeaveCriticalSection(&cs2);
}
技术分享图片

 2.4 环形锁申请

/* 多个线程申请锁的顺序形成相互依赖的环形:
*             A   -  B
*             |      |
*             C   -  D
*/

 三、死锁的避免策略

  死锁的代价是非常大的,有时候很难检测排查,因此需要在编程过程中尽可能的避免发生死锁。编程中为了避免死锁应该遵循如下策略

  1. 在编写多线程程序之前,首先编写正确的程序,然后再移植到多线程。
  2. 时刻检查自己写的程序有没有在跳出时忘记释放锁。
  3. 如果自己的模块可能重复使用一个锁,建议使用嵌套锁
  4. 对于某些锁代码,不要临时重新编写,建议使用库里面的锁,或者自己曾经编写的锁。
  5. 如果某项业务需要获取多个锁,必须保证锁的按某种顺序获取,否则必定死锁。
  6. 编写简单的测试用例,验证有没有死锁。
  7. 编写验证死锁的程序,从源头避免死锁。

多线程之——死锁(代码片段)

一、何为死锁采用多线程是为了改善系统资源的利用并提高系统的处理能力。然而,在实际使用过程中,会遇到新的问题——死锁。所谓死锁,就是多个线程因为资源竞争而造成的一种互相等待的状态,若无外力作用,这种状态... 查看详情

多线程之死锁定位及故障分析,尽可能避免线上事故(十三)

前两篇博文,我们介绍了线程池技术实现原理,这篇就够了以及线程池的拒绝策略,以及生产环境如何合理设置参数,比较彻底的介绍了线程池。我们对多线程已经介绍了很多的内容,针对多线程,高并发的分布式系统,对于共... 查看详情

python核心编程总结(五多任务编程之进程与线程)(代码片段)

✍、脑图时刻五、多任务编程之进程与线程✍、脑图时刻1、多任务编程1.1、多任务的概念1.2、多任务的执行方式1.3、进程1.4、多进程的使用1.4.1、获取进程编号1、获取当前进程编号2、获取当前父进程编号3、小结1.4.2、进程执行... 查看详情

python核心编程总结(五多任务编程之进程与线程)(代码片段)

✍、脑图时刻五、多任务编程之进程与线程✍、脑图时刻1、多任务编程1.1、多任务的概念1.2、多任务的执行方式1.3、进程1.4、多进程的使用1.4.1、获取进程编号1、获取当前进程编号2、获取当前父进程编号3、小结1.4.2、进程执行... 查看详情

多线程之死锁就是这么简单(代码片段)

...言只有光头才能变强回顾前面:ThreadLocal就是这么简单多线程三分钟就可以入个门了!多线程基础必要知识点!看了学习多线程事半功倍Java锁机制了解一下AQS简简单单过一遍Lock锁子类了解一下线程池你真不来了解一下吗?本篇... 查看详情

测开之并发编程篇・《并发并行线程队列进程和协程》(代码片段)

并发编程并发和并行多任务概念并发和并行同步和异步多线程threading模块介绍自定义线程类线程任务函数的传递多线程资源共享和资源竞争问题GIL全局解释锁互斥锁通过锁解决资源竞争问题死锁队列队列的方法FIFO先入先出队列LI... 查看详情

多线程等待唤醒机制之生产消费者模式

 上篇楼主说明了多线程中死锁产生的原因并抛出问题——死锁的解放方案,那么在本篇文章,楼主将引用一个KFC生产汉堡,顾客购买汉堡的过程来说明死锁解决方案及多线程的等待唤醒机制。简单地用一幅图来说明KFC生产汉堡... 查看详情

python并发编程多线程死锁现象与递归锁(代码片段)

... 一死锁现象所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待... 查看详情

并发编程

串行和并行:   串行:一个线程在处理操作   并行:多个线程在处理同一个操作 什么叫做并发编程:在多线程环境下,应用程序的执行 并发编程的目的:充分运用到资源,提高程序的效率 什么情况下用到并发编程:... 查看详情

linux系统编程多线程(代码片段)

多线程初识线程线程的概念线程的优缺点优点缺点了解pid(轻量级线程号)与tgid(线程组id)进程与线程概念解释同一所属组下多线程之间共享与独立的空间进程与线程的对比多进程与多线程对比线程控制线程的创建线程终止线程等... 查看详情

linux系统编程多线程(代码片段)

多线程初识线程线程的概念线程的优缺点优点缺点了解pid(轻量级线程号)与tgid(线程组id)进程与线程概念解释同一所属组下多线程之间共享与独立的空间进程与线程的对比多进程与多线程对比线程控制线程的创建线程终止线程等... 查看详情

多线程等待唤醒机制之生产消费者模式

  上篇楼主说明了多线程中死锁产生的原因并抛出问题——死锁的解放方案,那么在本篇文章,楼主将引用一个KFC生产汉堡,顾客购买汉堡的过程来说明死锁解决方案及多线程的等待唤醒机制。简单地用一幅图来说明KFC生产汉... 查看详情

ios底层探索之多线程—gcd源码分析(死锁的原因)(代码片段)

...探索分析!1.补充sync和async的区别是否可以开启新的线程执行任务任务的回调是否具有异步行、同步性是否产生死锁问题2.死锁源码分析在上篇博客分析,同步sync函数的流程是_dispatch_sync_f-->_dispatch_sync_f_ 查看详情

java并发编程04:死锁

1、什么是死锁多线程以及多进程改善了系统资源的利用率并提高了系统的处理能力。然而,并发执行也带来了新的问题--死锁。所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无... 查看详情

多线程编程的锁问题解析(锁竞争死锁活锁及daterace等)(代码片段)

本文是学习了Guancheng大神的文章后,根据文中的相关问题,进行代码分析,并且总结出这篇博客。原文地址:http://blog.csdn.net/freeelinux/article/details/54091140大神文章地址:http://www.parallellabs.com/2011/10/02/lock-in-p 查看详情

多线程之synchronized

Java并发编程:synchronized  虽然多线程编程极大地提高了效率,但是也会带来一定的隐患。比如说两个线程同时往一个数据库表中插入不重复的数据,就可能会导致数据库中插入了相同的数据。今天我们就来一起讨论下线程安... 查看详情

java--多线程之synchronized和lock;死锁(代码片段)

Java--多线程之并发,并行,进程,线程(一)_MinggeQingchun的博客-CSDN博客Java--多线程之终止/中断线程(二)_MinggeQingchun的博客-CSDN博客_java中断线程Java--多线程之join,yield,sleep;线程优先级&... 查看详情

(更新中)谈谈个人对java并发编程中(管程模型,死锁,线程生命周期等问题)见解

之前未曾接触过多线程编程 公司的项目开始用到多线程,所以自己谈谈个人对于并发编程的见解。 并发编程会导致线程不安全,常说的线程不安全指的是 多个线程操作一个共享数据,导致线程之间的读取到的数据不... 查看详情