C++死锁解决心得-1

上一篇 / 下一篇  2012-08-10 10:21:36 / 个人分类:C++

$T"Q XwcFl0  一、概述51Testing软件测试网-@3a*eJ+ZB:}

K u,M9XJ0  C++多线程开发中,容易出现死锁导致程序挂起的现象。

V(zpd~ u \.}g051Testing软件测试网S9[N.T z/Q

  解决步骤分为三步:

4DL zaZ3J"A051Testing软件测试网-u.Q%o*y&I&W

  1、检测死锁线程。51Testing软件测试网 LY2so0m&W(P

51Testing软件测试网}(sfa} r!` s

  2、打印线程信息。51Testing软件测试网/}Xu p0F:g

51Testing软件测试网3Z o6O%y}9TV0M#B

  3、修改死锁程序。51Testing软件测试网1~X1hY_:e'\

G%x^ H$t Sb0  二、程序示例

:t&IU/_"Yv,? y051Testing软件测试网l-d7q~'~2FA/o N8wZQ

  VS2005创建支持MFC的win32控制台程序。51Testing软件测试网s1t&sKJBDo4T9@

51Testing软件测试网W9D7B#LZ \7?N3X&a

  代码见示例代码DeadLockTest.cpp。

5qU(M_:Sx051Testing软件测试网xq9m-IpLd

51Testing软件测试网 p6q1z~6X

51Testing软件测试网pbd c+z)v)e!h

// DeadLockTest.cpp : Defines the entry point for the console application.51Testing软件测试网2|y1J4|1O#K
//

~*X W}&K`B Dx"Jy0

wG.t.n-ZB0#include "stdafx.h"
4@H%k}@3NJ lLU0#include "DeadLockTest.h"
51Testing软件测试网7t(y2|(T q,h0J

51Testing软件测试网m Qa2Y~4]

#ifdef _DEBUG51Testing软件测试网 wB0UY$h9Y+a
#define new DEBUG_NEW
2Xf'[#JC N0#endif
51Testing软件测试网4_/D1Nc S

K6Po7H'^!?M!I051Testing软件测试网%u3{&ESm
// The one and only application object

sc*d Cs0

%Z*H TerUfI2k0CWinApp theApp;51Testing软件测试网JSRUR+a+h7Lfc

.w'nFu#c0using namespace std;

V1B_w/du X,D0

5R:p~:N9D0CRITICAL_SECTION cs1;51Testing软件测试网 OpHQi_
CRITICAL_SECTION cs2;
tJ \] g#w0CRITICAL_SECTION csprint;
51Testing软件测试网Ly^/Hy ?

/h4v"E?)m-WJq(N0//初始化关键代码段
6e0U}dQ5V*}d0void InitMyCriticalSection();
z9Zj%Sd"EP0//删除关键代码段51Testing软件测试网!F9@8V0wR2c b5u:A^
void DeleteMyCriticalSection();
'N0_.}9zA0//打印信息51Testing软件测试网&EqZ7v f#W _&D
void PrintString(const CString& strInfo);

l Pnf"`0

7b"p7pv7k3k\]Va0DWORD WINAPI Thread1(LPVOID lpParameter);
yg"M E,SJ%feX?0DWORD WINAPI Thread2(LPVOID lpParameter);

kEQUm:w1u,_)i6[f0

;O-xi8p$}1t f"M0int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
-o ^'qf*Hk5V \D,^x0{51Testing软件测试网b`,f]4I*G
    int nRetCode = 0;
51Testing软件测试网)p+p],|@,Nq

4JL)ZxVg {o e1t0    // initialize MFC and print and error on failure
x?D#q0X F*M0    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))51Testing软件测试网3l:\X tC
    {
z;FRa2l~)S-R7L0        // TODO: change error code to suit your needs
/x aw9H.P7]!{$L)l$[0        _tprintf(_T("Fatal Error: MFC initialization failed\n"));51Testing软件测试网F1oTP"K dX
        nRetCode = 1;

y&N[&zqpui)f1C0

Wu b|*wC$@&R0        return nRetCode;
w nud)\i+n0    }

-b8?*wf`!J/_0

TK;W[[)E'yY0    //初始化关键代码段51Testing软件测试网Kyv\!U;l,bS.I
    InitMyCriticalSection();
51Testing软件测试网\,ah5}tob Pq

V7c&e,L ZU hk P b)k0    //创建线程
(Zg4C y6S.Ojrp6u0    HANDLE hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
yX4fPJ@X&kK^,f!W0    HANDLE hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);

_`%OE]1`!u _0

*]*yy~8o\q0    //等待线程结束51Testing软件测试网([7Q,C%^ C(t,^)Bo
    WaitForSingleObject(hThread1, INFINITE);
*p6OD+T3[S!c4Q0    WaitForSingleObject(hThread2, INFINITE);

X:m geQ051Testing软件测试网-L;pe\8u

    //关闭线程句柄51Testing软件测试网6e"~k4zX4f#Q
    CloseHandle(hThread1);
%m}b#N&L5k4]P0    CloseHandle(hThread2);

od*y{3Hd b7M0

ac&MiWs|I BS0    //释放关键代码段51Testing软件测试网)w6byZ3h5Q
    DeleteMyCriticalSection();

AswVj.`-B051Testing软件测试网6HY;eh/D1d x9m

    return nRetCode;
&k;C@!VF&i)YblE g]0}

#N9]N"QO9q"r9qU051Testing软件测试网AX3I$^8UM J_

void InitMyCriticalSection()51Testing软件测试网?`N9j#\(]Q;w
{
5P Z}9k#uS? yH|0    InitializeCriticalSection(&cs1);51Testing软件测试网g|5g~[9Y4H'a
    InitializeCriticalSection(&cs2);
,E}2i o[Y"xK0    InitializeCriticalSection(&csprint);51Testing软件测试网 Xqs`S\,jqXfo
}

j;QD2w6On#_%Q8EI*j0

,N3}5\3_x0void DeleteMyCriticalSection()
"sV#Q0B$|0{
l.wP?.S3va\ O0    DeleteCriticalSection(&cs1);
q,V!?O{JZ^+Gx0    DeleteCriticalSection(&cs2);51Testing软件测试网LgW!]8D[6D;D
    DeleteCriticalSection(&csprint);
7v&q7X6N,P'}Z0}
51Testing软件测试网U1rf?M5{,a

TQ"Gl}RDZ~0DWORD WINAPI Thread1(LPVOID lpParameter)
F'w8Q8D1{ T4C0{51Testing软件测试网UUD&xZ7?K
    for (int i = 0; i < 5; i++)
p? E6Rg#p(o G0    {
M'o I5?9CD3vFS0        EnterCriticalSection(&cs1);
't2j*I(_ V0        Sleep(500);51Testing软件测试网h5ql9rd~ T|r
        EnterCriticalSection(&cs2);

v4ybtA;h p0

$gu*_ n%BbVP~$R?0        PrintString(_T("Thread1"));51Testing软件测试网:jg*c#hB G4K'yql

\B(A6{&K2? Eb y3H8O0        LeaveCriticalSection(&cs2);51Testing软件测试网;^K h rlw5iX3_R
        LeaveCriticalSection(&cs1);
N/h*Uo!`-{0}S0    }

YEDo7j c!t$[051Testing软件测试网,a9oRY ~yQ a

    return 1;
;XOfK!w7X6a Q4~0z8S+Y0}

'_9p0c4s5k-Ve a051Testing软件测试网9?*Tlb+DM)Y6s&d^

DWORD WINAPI Thread2(LPVOID lpParameter)
p:SWmAfhFG#Y;s3@0{51Testing软件测试网8oUGR#kjS+c"C
    for (int i = 0; i < 5; i++)51Testing软件测试网^j gwnA
    {51Testing软件测试网8Q~Lu5B
        EnterCriticalSection(&cs2);
7ZuR9CPRn0        Sleep(500);51Testing软件测试网e+NJ{ C)L uA1I
        EnterCriticalSection(&cs1);
51Testing软件测试网7kQUx#o%ED3v

Fk2n8d:a9F0        PrintString(_T("Thread2"));51Testing软件测试网3~bR5a&m9m`(Uqt

51Testing软件测试网H7vBON-XWp Z

        LeaveCriticalSection(&cs1);
1c!R;A*r-s} G&M6k0        LeaveCriticalSection(&cs2);
.E+n[n ms0    }
51Testing软件测试网K@ _QSp^+\

51Testing软件测试网X K/Ki*A-a

    return 1;51Testing软件测试网6P1qxQg5F$CG)Qm2^
}
51Testing软件测试网6D.cBF U

W*O/s2sR(r;S)w0void PrintString(const CString& strInfo)51Testing软件测试网-t1h A\{a+t'Ye
{51Testing软件测试网7BPxRrh1S)gH
    EnterCriticalSection(&csprint);51Testing软件测试网k-l-T@t:UF
    wcout<<(const TCHAR*)strInfo<<endl;51Testing软件测试网6b7o!V4KTV-~ x9f7oQ
    LeaveCriticalSection(&csprint);51Testing软件测试网0[#X9i n/w;u6Hzr
}
51Testing软件测试网;JD0n%KG~

51Testing软件测试网9G"E8^:FLZS_v6b

  运行DeadLockTest.exe,程序挂起。

0ul:cU0A\SC0

2iR9b,ZE5O0  三、死锁检测

)I+X"Lu P&R5~b e*m;X0

)Vr X#G|~R`0  检测工具见《Windows核心编程》,第9章9.8.6节LockCop检测工具。

@*ruR6C7W0d5I)N051Testing软件测试网UpaM8fUc

  工具源码地址:http://www1.wintellect.com/Resources/Details/86。51Testing软件测试网F N:l A,@r){

]F.m Z'y V(h2y0  LockCop可使用vs2010编译成功。51Testing软件测试网$Z eR9G"EG bh_

51Testing软件测试网qN/OK%R-_I

  备注:该工具使用了Windows Vista/ 7提供的WCT API,故需要在Windows Vista/ 7系统运行LockCop检测工具。51Testing软件测试网&W)S)Z7{qY%D

51Testing软件测试网5Yi2u r P!Z2M

  检测,挂起的DeadLockTest.exe,得到线程信息。

H|dz1d!N0

m5KMw%Ft$S0

  检测到程序挂起由死锁引起。

8w$]1gM"n;H.BGX0

  线程4014:等待线程772、线程4012完成。51Testing软件测试网$E/Pl"RX2`6~Ufa
  线程772:拥有关键代码段A,等待关键代码段B(被线程4012拥有)。
0y8F8y!JJ+K)c0  线程4012:拥有关键代码段B,等待关键代码段A(被线程772拥有)。

,s G H;Mk0

  线程772与4012互相等待,程序发生死锁现象。

p.@ }-W)G0

TAG:

 

评分:0

我来说两句

Open Toolbar