种简单的线程死锁检测方法及其VC_应用
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
$%&’ F,(%)*+ 56 8?40’(%)*@%,&.%1 &&A4.B,-.0,)4+ 5CG4<%$4+H./&-5 " I40$481&.&)0(94).&%,+;<=)-5 " E 8GBJB8DI=978JBKL <=)- " )%,-. )/01 H<=3&(4 " &,. <=(&,4" ?MKG? <=I%)*J&<4 " E" N’43&,4 7LJ7G=IK8O+)-5 N’43&,4 I7DQ7=IK8O+)-5 ##被封装起来的临界区 ## 进入临界区的文件 ## 进入临界区是的确切位置 ## 被锁住的时间 ##离开临界区
++8I6 GI9B86B 8I6 MB=8=MKL 9:;(./2(*/I=G 7K76B K@KLJG6G K 7B=@M=7L6 9: 8I6 ;GKA6 9: MB=8=MKL G6M8=9@+ G6M8=9@ =G # 8I6 D6886B =8 =GN /I6@ =8 A=>6G K G=<7L6 K@F 6::6M8=>6 OKJ 9: F6KF L9MP F686M8=9@ DKG6F 9@
收稿日期 ! !""#$"%$!& 作者简介 ! 郑冬黎 !’&()$ "# 女 # 湖北襄樊人 # 工学硕士 $
$ "\ $
湖北汽车工业学院学报
!""! 年 " 月
占用的时间越短越好 ! 事实上对任何应用程序 " 如果某个互斥锁被一个线程持续占用超过# 秒 " 那么开发者 就应仔细检查该互斥锁的的应用逻辑 " 因为其中很可能存在着逻辑错误 " 即使它不引起线程死锁 " 也必将 #$ 总之它必须被排除 % 成为一个性能瓶颈$ 因此可以通过监视应用程序中所有的互斥锁 "及时发现任何可能出现的死锁并准确给出其确切位置 !
*) JJ-3DG3和 -3;L 方法 " 分别启动和停止死锁监视器 ’ 包括启动和终止后台监视线程 (
R) <?DHH %+;<=I L2Y?F< &
第 !! 卷 第 " 期
郑冬黎 & 一种简单的线程死锁检测方法及其 Q8aa 应用
! !" !
!"## 构造函数和析构函数 # 分别初试化和销毁临界区
$%&’ (%)*+)%,-. )/01 23&(4 $)%,-. &,. (&,456 7,.4181&.&)0(94).&%,:;<=)->"
%
## 进入临界区 ## 记录位置信息和时间信息 ## 在登记中心登记 ## 在登记中心注销
8?40’(%)*@%,&.%1 &&A4.B,-.0,)4: >CD’’:2./&-> " E
测试 "
测试 d
测试程序的主函数如下 &
$%&’ <0&,: 56 8?40’(%)*@%,&.%1 &&A4.B,-.0,)4: 5<%,&.%1C9.01.: 5"
!" ## 测试 c 和 "
百度文库
8J4-.80-4d: 5C.4-.: 5 " 8?40’(%)*@%,&.%1 &&A4.B,-.0,)4: 5<%,&.%1C9.%S: 5 " E
!"#$%& ’&()*+ *, -).&/+ 0&/+ 1*23 0&(&2("*4 /4+ 5#$%&#&4(/("*4 ,*. 6788
!"#$% &’$%()
!5678* 9: 2;89<98=>6 ?@A=@66B=@A # C;D6= 2;89<98=>6 E@F;G8B=6G E@G8=8;86# HI=JK@ ..!""! # +I=@K"
#
在$%&&中监视互斥锁的方法
在 $%&& 中可以使用两种互斥锁 & 临界区 %’()(%*+,-.%)(/0 和互斥量 12345 % 为简单起见起见 " 本文
以%’()(%*+6-.%)(/0为例进行分析 % 为了监视每个互斥锁的使用情况 " 需要建立一个全局的登记中心用 于记录每个互斥锁的使用情况 % 每当一个锁被获取时就在此登记 它被获取时的精确时间和确切位置 ’ 利用 ,,7(+.,, 和 ,,+(0.,, () 当一个锁被释放时就从登记中心删除其对应的记录 % 这样一条记 录在登记中心存在的时间就是其对应的互斥锁被一个线程持续 占用有的时间 % 现在可以启动一个后台线程周期性的检查登记中 心的每个记录 " 一旦发现某个记录存在的时间超过 # 秒就立即报 警并显示确切位置 % 示意图如图8%
U;FE *EE>%+;<= Z?;<=@I (AA4G+;<=S4?L4G ?;<=4GXQ,(AA4G+;<=@) JJ 锁住 Q,+;<=H ,FAH3DA<4[Q,+;<=H[FAH4G3XZ?;<=@ ) R U;FE ’4Q;U4X%+;<= Z?;<=@I (AA4G+;<=S4?L4G ?;<=4GXQ,(AA4G+;<=@) JJ 锁住 Q,+;<=H ,FAH3DA<4[Q,+;<=H[4GDH4XZ?;<=@) R
图8 监视互斥锁方法示意图
9
$%:&线程死锁检测器的实现
下 面 给 出 一 个 $% && 线 程 死 锁 检 测 器 的 具 体 实 现 " 它 由 两 部 分 组 成 &%+;<= 封 装 临 界 区
%’()(%*+,-.%)(/0"进入临界区时%+;<=>?;<= 方法@ 将自己注册到登记中心 " 离开临界区时 %+;<=>2A?;<= 方 法 B在登记中心注销自己的记录 )%C4DE?;<=1;AF3;G 是登记中心 " 记录每个 %+;<= 对象的使用情况 " 其内部启 动一个监视线程 " 周期性的检查每个登记项的存在时间是否超过#秒 %
+)-C(%)*+==PBI7== $==IBL7==55 ## 定义两个宏方便 8(%)* 的使用 +)-CF,(%)*+ 55 "
?MKG? MBLDRB 8?40’(%)*@%,&.%1 &&@%,&.%1J/140’+IRQKB? S010<56 ## 监视线程的线程体 8?40’(%)*@%,&.%1 HSJ/&- T +8?40’(%)*@%,&.%1 H5S010< " U/&(4+M0&.P%19&,V(4KWX4).:SJ/&-YZ<=/7[&.7$4,. $"\\\5 ] T MDBJ=K^_78J=\56 6 B,,41I%)*‘4(S41 (%)*41:SJ/&-YZ<=B,,41I%)*5 " ## 锁住所以登记记录本 I%)*94. &&&.410.%1 &. " 3%1:&. T SJ/&-YZ<=I%)*-CW4V&,: 5" &. ] T SJ/&-YZ<=I%)*-C4,’: 5 " &.aa56 &3:A4.J&)*8%F,.: 5 Y :H&.5YZ<=I%)*J&<4 Z "\\\56#H 发出警告 H#E ## 发现一条记录超过两秒 EEE 14.F1, \ "E
*) JJ 构造函数和析构函数 ! %C4DE?;<=1;AF3;G使用单件模式 " 限于篇幅相关代码省去
<?DHH (AA4G+;<=I * R Q,(AA4G+;<= ) JJ 内部锁是 %+;<= 的简化版本 " 参见 %+;<= JJ 锁助手 " 在构造方法锁定一个 (AA4G+;<= 对象 " 析构时释放该对象 JJ 退出信号 " 用于通知监视线程退出 JJ 监视线程 S*0C+. Q,1;AF3;G)TG4DE ) JJ 监视线程的句柄 H3D3F< CV/’C V(0*W( 1;AF3;G)TG4DEX+W$/(C LDGDQB)
第 4% 卷 第 ! 期
湖北汽车工业学院学报
7"’ 8 9%
:" 8 !
!;66. 年 1 月
!"#$%&’ "( )#*+, -#."/".,0+ 1%2#3.$,+3 1%3.,.#.+
R;@N 566.
一种简单的线程死锁检测方法及其-+,,应用
郑冬黎
! 湖北汽车工业学院 汽车工程系 # 湖北 十堰 ..!""! "
摘
要 * 分析了互斥锁的使用原则 + ++ 临界区越小越好 # 基于此原则提出了一种简单 % 高效的线程死锁检测的方
法 # 实现了一个 -+,, 线程死锁检测器 $ 关键字 * -+,,, 线程 , 死锁 , 检测 中图分类号 ! /0#’1 文献标识码 ! 2 文章编号 ! ’""%3).%# !!"". ""!4""1($".
<?DHH %+;<=) <?DHH %C4DE?;<=1;AF3;GI JJ %C4DE?;<=1;AF3;G 是线程安全的 JJ 记录每个互斥锁的使用情况 3KL4E4M H3E&&H43N<;AH3 %+;<= OP Q,+;<=H ) <?DHH (AA4G+;<=S4?L4GI * R S*0C+. Q,T.5F3.U4A3) L2Y?F< &
8I6 K@KLJG=GN 2@F KLG9 =8 MB6K86G K F6KF L9MP F686M89B :9B -+Q, KMM9BF=@A 89 8I=G <68I9FN <&= >*.+; *-+,,, 8IB6KF, F6KF L9MP, F686M8=9@
在一个复杂的应用程序中定位 % 排除线程死锁问题通常是很困难的 #及时发现死锁现象并确定其具体 位置对解决线程死锁非常有帮助 $ & 资源分配图 ’ 法是经典的死锁检测方法 #( 程序员 ) 杂志 !""#*"% 期 &) 页 上 ( 使用锁监视器检测+,, 中的死锁 ) 给出的死锁检测方法就是该方法的一个具体实现 $ & 资源分配图 ’ 法 虽然强大 # 但其实现较复杂 # 同时由于寻找资源分配图中的闭环回路的计算量较大 # 该方法对系统的性能 影响较明显 $ 另一方面难以解决的死锁现象往往发生频率很低 # 因此在实际应用中更希望用一种简单而高 效的方法来检测可能出现的死锁 # 本文将介绍一种这样的死锁检测方法 $
d 个线程 $ 通过一互斥锁访问同一共享变量 " 该用例逻辑无误 $ 不会出现死锁现象 ’
启动两个线程来访问同一个共享变量 " 访问共享变量前每个线程必须同时获取两个 互斥锁 $ 但两个线程获取锁的顺序相反 ’ 这是教科书中给出的一种典型死锁情形 ’ 启动两个线程通过一个互斥锁访问同一个共享变量 ’ 逻辑正确无误 $ 但在特定情况 下对共享资源的访问实际上是一个不可能完成的任务 $ 这将导致线程死锁的发生 ’
限于篇幅 $测试 c("的代码省去 )测试"的代码与测试d 非常相似 *’ 测试 d的代码如下 &
)(0-- 8J4-.80-4d6
+ ^H +
#$%&’ ()*%&’ ! +,- ()./01230-0!
湖北汽车工业学院学报
!""! 年 " 月
4-0-+& 35673 589:;8 </120= "$;>683 ?010(#@ #<24-#042A B?</+4 C "#<24-#042A B $?010( ! D%1 %+,- + C E ! + F GHH ! +II $@ J9<J7)$6#K "?</+4LM()*%&’$! ?</+4LM()./01230-0II ! .*22?NGH B GHHHO ! R 12-S1, H ! R ?ST*+& ’ U%+= -24-N O@ ( R ! PP 启动两个测试线程 & 线程方法是 </120= R! PP 相对于 Q秒钟是一个不可能完成的任务 & 在实际应用中 $J:>J)$6#KN?</+4LM()*%&’O ! PP 这里可能是一个因协议失效而不可能完成的网络操作
’
原
理
在多线程应用中为了保证系统状态的完整性和一致性 # 必须利用互斥锁对共享资源进行保护 $ 互斥锁 可以为共享资源建立临界区 *当一个线程需要访问共享资源时首先获取互斥锁进入临界区 #然后访问共享 资源 #最后释放互斥锁离开临界区 $ 如果互斥机制使用不当使得一个互斥锁被一个线程无限期的占用 # 就 会引起线程死锁 $ 此时其他想进入临界区的线程将一直等待 #应用程序的全部或者一部分停止工作 $ 在一 个复杂的应用程序中定位 % 排除线程死锁是一个很困难的而耗时的工作 #快速检测并定位可能发生的死锁 对解决死锁问题是非常重要的 $ 互斥锁是共享资源的保护神 # 它确保任何时刻只有一个线程可以访问共享资源 $ 临界区的效果是多个 线程访问同一个临界区时被串行化了 # 因此损失了并行度进而影响系统的整体效率 $ 为降低临界区对系统 整体效率的影响 # 在使用临界区时有这样一个原则 * 任一线程只在临界区内做最必要的工作 $ 因为临界区 是由互斥锁建立起来的 # 所以这个原则也可以这样描述 * 任意给定的互斥锁 # 任意时刻被同一个线程持续
b
测
试
为检验8?40’(%)*@%,&.%1 的实际效果 $ 设计了三个典型的测试用例 $ 见表c’
表 c 测试用例描述
用例 测试 c 测试用例描述 预期结果 程序正常结束 检测到死锁 $ 异常终止 : 为让死 锁更容易出现 $ 做了特殊处理 5 检测到死锁 $ 异常终止 ) 此情形在 实际应用中出现时更难以定位 *