多线程编程之线程死锁问题
2018-01-18 18:48
387 查看
在多线程编程中,除了要解决数据访问的同步与互斥之外,还需要解决的重要问题就是多线程的死锁问题。所谓死锁: 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去。
一、死锁原因与形成条件
死锁形成的原因:
系统资源不足
进程(线程)推进的顺序不恰当;
资源分配不当
死锁形成的条件:
互斥条件:所谓互斥就是进程在某一时间内独占资源。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
从编程经验上来讲,形成死锁的一般原因有以下几种:
个人使用锁的经验差异。
程序模块使用锁的差异。
工程代码版本之间的差异。
工程代码分支之间的差异。
修改代码和重构代码带来的差异。
二、常见死锁形成的场景
死锁形成的常见情况有以下几种:
2.1 忘记释放锁
2.2 单线程重复申请锁
2.3 多线程多锁申请
2.4 环形锁申请
三、死锁的避免策略
死锁的代价是非常大的,有时候很难检测排查,因此需要在编程过程中尽可能的避免发生死锁。编程中为了避免死锁应该遵循如下策略:
在编写多线程程序之前,首先编写正确的程序,然后再移植到多线程。
时刻检查自己写的程序有没有在跳出时忘记释放锁。
如果自己的模块可能重复使用一个锁,建议使用嵌套锁。
对于某些锁代码,不要临时重新编写,建议使用库里面的锁,或者自己曾经编写的锁。
如果某项业务需要获取多个锁,必须保证锁的按某种顺序获取,否则必定死锁。
编写简单的测试用例,验证有没有死锁。
编写验证死锁的程序,从源头避免死锁。
一、死锁原因与形成条件
死锁形成的原因:
系统资源不足
进程(线程)推进的顺序不恰当;
资源分配不当
死锁形成的条件:
互斥条件:所谓互斥就是进程在某一时间内独占资源。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
从编程经验上来讲,形成死锁的一般原因有以下几种:
个人使用锁的经验差异。
程序模块使用锁的差异。
工程代码版本之间的差异。
工程代码分支之间的差异。
修改代码和重构代码带来的差异。
二、常见死锁形成的场景
死锁形成的常见情况有以下几种:
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 */
三、死锁的避免策略
死锁的代价是非常大的,有时候很难检测排查,因此需要在编程过程中尽可能的避免发生死锁。编程中为了避免死锁应该遵循如下策略:
在编写多线程程序之前,首先编写正确的程序,然后再移植到多线程。
时刻检查自己写的程序有没有在跳出时忘记释放锁。
如果自己的模块可能重复使用一个锁,建议使用嵌套锁。
对于某些锁代码,不要临时重新编写,建议使用库里面的锁,或者自己曾经编写的锁。
如果某项业务需要获取多个锁,必须保证锁的按某种顺序获取,否则必定死锁。
编写简单的测试用例,验证有没有死锁。
编写验证死锁的程序,从源头避免死锁。
相关文章推荐
- [置顶] 多线程编程之线程死锁问题
- 多线程编程之线程死锁问题
- 多线程编程之线程死锁问题 转载
- java高级多线程编程--关于线程的停止问题
- java高级多线程编程--关于线程的停止问题
- 黑马程序员------多线程(No.2)(死锁、线程间通信、生产者消费者问题)
- 【面经笔记】线程、多线程 - 死锁、读写、消费者问题、TLS【续2】
- 多线程编程的锁问题解析(锁竞争死锁活锁及Date Race等)
- 多线程中的线程通信以及死锁问题
- 多线程编程:线程死锁的原因以及解决方法
- Java编程之多线程死锁与线程间通信简单实现代码
- Java笔记3 多线程<1>线程概述、多线程的创建、多线程的安全问题、静态同步函数的锁、死锁
- Linux 多线程编程----线程见同步问题
- Qt中采用多线程实现Socket编程-跨线程调用问题
- java高级多线程编程--关于线程的停止问题
- java高级多线程编程--关于线程的停止问题
- java高级多线程编程--关于线程的停止问题
- Unity3d 多线程编程 线程和主线程(UI)交互实现问题
- java高级多线程编程--关于线程的停止问题
- 编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程