<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    C++死鎖解決心得

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接 一、 概述
    C++多線程開發中,容易出現死鎖導致程序掛起的現象。

    關于死鎖的信息,見百度百科http://baike.baidu.com/view/121723.htm

    解決步驟分為三步:
    1、檢測死鎖線程。
    2、打印線程信息。
    3、修改死鎖程序。

    二、 程序示例
    VS2005創建支持MFC的win32控制臺程序。
    代碼見示例代碼DeadLockTest.cpp。
    [cpp] view plaincopy
    1. // DeadLockTest.cpp : Defines the entry point for the console application.  
    2. //  
    3.   
    4. #include "stdafx.h"  
    5. #include "DeadLockTest.h"  
    6.   
    7. #ifdef _DEBUG  
    8. #define new DEBUG_NEW  
    9. #endif  
    10.   
    11.   
    12. // The one and only application object  
    13.   
    14. CWinApp theApp;  
    15.   
    16. using namespace std;  
    17.   
    18. CRITICAL_SECTION cs1;  
    19. CRITICAL_SECTION cs2;  
    20. CRITICAL_SECTION csprint;  
    21.   
    22. //初始化關鍵代碼段  
    23. void InitMyCriticalSection();  
    24. //刪除關鍵代碼段  
    25. void DeleteMyCriticalSection();  
    26. //打印信息  
    27. void PrintString(const CString& strInfo);  
    28.   
    29. DWORD WINAPI Thread1(LPVOID lpParameter);  
    30. DWORD WINAPI Thread2(LPVOID lpParameter);  
    31.   
    32. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])  
    33. {  
    34.     int nRetCode = 0;  
    35.   
    36.     // initialize MFC and print and error on failure  
    37.     if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))  
    38.     {  
    39.         // TODO: change error code to suit your needs  
    40.         _tprintf(_T("Fatal Error: MFC initialization failed\n"));  
    41.         nRetCode = 1;  
    42.   
    43.         return nRetCode;  
    44.     }  
    45.   
    46.     //初始化關鍵代碼段  
    47.     InitMyCriticalSection();  
    48.   
    49.     //創建線程  
    50.     HANDLE hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);  
    51.     HANDLE hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);  
    52.   
    53.     //等待線程結束  
    54.     WaitForSingleObject(hThread1, INFINITE);  
    55.     WaitForSingleObject(hThread2, INFINITE);  
    56.   
    57.     //關閉線程句柄  
    58.     CloseHandle(hThread1);  
    59.     CloseHandle(hThread2);  
    60.   
    61.     //釋放關鍵代碼段  
    62.     DeleteMyCriticalSection();  
    63.   
    64.     return nRetCode;  
    65. }  
    66.   
    67. void InitMyCriticalSection()  
    68. {  
    69.     InitializeCriticalSection(&cs1);  
    70.     InitializeCriticalSection(&cs2);  
    71.     InitializeCriticalSection(&csprint);  
    72. }  
    73.   
    74. void DeleteMyCriticalSection()  
    75. {  
    76.     DeleteCriticalSection(&cs1);  
    77.     DeleteCriticalSection(&cs2);  
    78.     DeleteCriticalSection(&csprint);  
    79. }  
    80.   
    81. DWORD WINAPI Thread1(LPVOID lpParameter)  
    82. {  
    83.     for (int i = 0; i < 5; i++)  
    84.     {  
    85.         EnterCriticalSection(&cs1);  
    86.         Sleep(500);  
    87.         EnterCriticalSection(&cs2);  
    88.   
    89.         PrintString(_T("Thread1"));  
    90.   
    91.         LeaveCriticalSection(&cs2);  
    92.         LeaveCriticalSection(&cs1);  
    93.     }  
    94.   
    95.     return 1;  
    96. }  
    97.   
    98. DWORD WINAPI Thread2(LPVOID lpParameter)  
    99. {  
    100.     for (int i = 0; i < 5; i++)  
    101.     {  
    102.         EnterCriticalSection(&cs2);  
    103.         Sleep(500);  
    104.         EnterCriticalSection(&cs1);  
    105.   
    106.         PrintString(_T("Thread2"));  
    107.   
    108.         LeaveCriticalSection(&cs1);  
    109.         LeaveCriticalSection(&cs2);  
    110.     }  
    111.   
    112.     return 1;  
    113. }  
    114.   
    115. void PrintString(const CString& strInfo)  
    116. {  
    117.     EnterCriticalSection(&csprint);  
    118.     wcout<<(const TCHAR*)strInfo<<endl;  
    119.     LeaveCriticalSection(&csprint);  
    120. }  

    運行DeadLockTest.exe,程序掛起。

    三、 死鎖檢測
    檢測工具見《Windows核心編程》,第9章9.8.6節LockCop檢測工具。
    工具源碼地址:http://www1.wintellect.com/Resources/Details/86

    LockCop可使用vs2010編譯成功。
    備注:該工具使用了Windows Vista/ 7提供的WCT API,故需要在Windows Vista/ 7系統運行LockCop檢測工具。

    檢測,掛起的DeadLockTest.exe,得到線程信息。
    RFID設備管理軟件
    檢測到程序掛起由死鎖引起。

    線程4014:等待線程772、線程4012完成。
    線程772:擁有關鍵代碼段A,等待關鍵代碼段B(被線程4012擁有)。
    線程4012:擁有關鍵代碼段B,等待關鍵代碼段A(被線程772擁有)。

    線程772與4012互相等待,程序發生死鎖現象。

    四、 打印信息
    為了便于查找問題,我們加上線程打印信息。
    打印線程名稱、線程ID以及關鍵代碼段進入信息。

    [cpp] view plaincopy
    1. DWORD WINAPI Thread1(LPVOID lpParameter)  
    2. {  
    3.     CString strThreadID = _T("");  
    4.     strThreadID.Format(_T("%d"), GetCurrentThreadId());  
    5.   
    6.     CString strPrintInfo = _T("");  
    7.   
    8.     for (int i = 0; i < 5; i++)  
    9.     {  
    10.         EnterCriticalSection(&cs1);  
    11.   
    12.         strPrintInfo = _T("");  
    13.         strPrintInfo += _T("Thread1 ");  
    14.         strPrintInfo += strThreadID;  
    15.         strPrintInfo += _T(" EnterCriticalSection(&cs1)");  
    16.   
    17.         PrintString(strPrintInfo);  
    18.   
    19.         Sleep(500);  
    20.         EnterCriticalSection(&cs2);  
    21.   
    22.         strPrintInfo = _T("");  
    23.         strPrintInfo += _T("Thread1 ");  
    24.         strPrintInfo += strThreadID;  
    25.         strPrintInfo += _T(" EnterCriticalSection(&cs2)");  
    26.   
    27.         PrintString(strPrintInfo);  
    28.   
    29.         LeaveCriticalSection(&cs2);  
    30.         LeaveCriticalSection(&cs1);  
    31.     }  
    32.   
    33.     return 1;  
    34. }  
    35.   
    36. DWORD WINAPI Thread2(LPVOID lpParameter)  
    37. {  
    38.     CString strThreadID = _T("");  
    39.     strThreadID.Format(_T("%d"), GetCurrentThreadId());  
    40.   
    41.     CString strPrintInfo = _T("");  
    42.   
    43.     for (int i = 0; i < 5; i++)  
    44.     {  
    45.         EnterCriticalSection(&cs2);  
    46.   
    47.         strPrintInfo = _T("");  
    48.         strPrintInfo += _T("Thread2 ");  
    49.         strPrintInfo += strThreadID;  
    50.         strPrintInfo += _T(" EnterCriticalSection(&cs2)");  
    51.   
    52.         PrintString(strPrintInfo);  
    53.   
    54.         Sleep(500);  
    55.   
    56.         EnterCriticalSection(&cs1);  
    57.   
    58.         strPrintInfo = _T("");  
    59.         strPrintInfo += _T("Thread2 ");  
    60.         strPrintInfo += strThreadID;  
    61.         strPrintInfo += _T(" EnterCriticalSection(&cs1)");  
    62.   
    63.         PrintString(strPrintInfo);  
    64.   
    65.         LeaveCriticalSection(&cs1);  
    66.         LeaveCriticalSection(&cs2);  
    67.     }  
    68.   
    69.     return 1;  
    70. }  

    運行結果如下。

    RFID設備管理軟件

    五、 死鎖修改
    線程互斥進行修改,Thread1與Thread2對關鍵代碼段的進入與退出順序改為相同。程序運行正常。
    修改后線程代碼。

    [cpp] view plaincopy
    1. DWORD WINAPI Thread1(LPVOID lpParameter)  
    2. {  
    3.     for (int i = 0; i < 5; i++)  
    4.     {  
    5.         EnterCriticalSection(&cs1);  
    6.         Sleep(500);  
    7.         EnterCriticalSection(&cs2);  
    8.   
    9.         PrintString(_T("Thread1"));  
    10.   
    11.         LeaveCriticalSection(&cs2);  
    12.         LeaveCriticalSection(&cs1);  
    13.     }  
    14.   
    15.     return 1;  
    16. }  
    17.   
    18. DWORD WINAPI Thread2(LPVOID lpParameter)  
    19. {  
    20.     for (int i = 0; i < 5; i++)  
    21.     {  
    22.         EnterCriticalSection(&cs1);  
    23.         Sleep(500);  
    24.         EnterCriticalSection(&cs2);  
    25.   
    26.         PrintString(_T("Thread2"));  
    27.   
    28.         LeaveCriticalSection(&cs2);  
    29.         LeaveCriticalSection(&cs1);  
    30.     }  
    31.   
    32.     return 1;  
    33. }  

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全