多线程的那点儿事(之避免死锁)

本文介绍了预防多线程程序中出现死锁的七大注意事项,并通过示例代码展示了如何改写锁的申请与释放函数,以确保锁的安全使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

预防死锁的注意事项:

(1)在编写多线程程序之前,首先编写正确的程序,然后再移植到多线程

(2)时刻检查自己写的程序有没有在跳出时忘记释放锁

(3)如果自己的模块可能重复使用一个锁,建议使用嵌套锁

(4)对于某些锁代码,不要临时重新编写,建议使用库里面的锁,或者自己曾经编写的锁

(5)如果某项业务需要获取多个锁,必须保证锁的按某种顺序获取,否则必定死锁

(6)编写简单的测试用例,验证有没有死锁

(7)编写验证死锁的程序,从源头避免死锁


    首先,定义基本的数据结构和宏,

  1. typedef struct _LOCK_INFO 
  2.     char lockName[32]; 
  3.     HANDLE hLock; 
  4. }LOCK_INFO: 
  5.  
  6. typedef struct _THREAD_LOCK 
  7.     int threadId; 
  8.     LOCK_INFO* pLockInfo[32]; 
  9. }THREAD_LOCK; 
  10.  
  11. #define CRITICAL_SECTION_TYPE 1 
  12. #define MUTEX_LOCK_TYPE       2 
  13. #define SEMAPHORE_LOCK_TYPE   3 
  14. #define NORMAL_LOCK_TYPE      4 
  15.  
  16. #define WaitForSingleObject(a, b) \ 
  17.         WaitForSingleObject_stub((void*)a, NORMAL_LOCK_TYPE) 
  18.  
  19. #define EnterCriticalSection(a) \ 
  20.         WaitForSingleObject_stub((void*)a, CRITICAL_SECTION_TYPE) 
  21.  
  22. #define ReleaseMutex(a) \ 
  23.         ReleaseLock_stub((void*)a, MUTEX_LOCK_TYPE)) 
  24.  
  25. #define ReleaseSemaphore(a, b, c) \ 
  26.         ReleaseLock_stub((void*)a, SEMAPHORE_LOCK_TYPE)) 
  27.  
  28. #define LeaveCriticalSection(a) \ 
  29.         ReleaseLock_stub((void*)a, CRITICAL_SECTION_TYPE)) 
typedef struct _LOCK_INFO
{
    char lockName[32];
    HANDLE hLock;
}LOCK_INFO:

typedef struct _THREAD_LOCK
{
    int threadId;
    LOCK_INFO* pLockInfo[32];
}THREAD_LOCK;

#define CRITICAL_SECTION_TYPE 1
#define MUTEX_LOCK_TYPE       2
#define SEMAPHORE_LOCK_TYPE   3
#define NORMAL_LOCK_TYPE      4

#define WaitForSingleObject(a, b) \
        WaitForSingleObject_stub((void*)a, NORMAL_LOCK_TYPE)

#define EnterCriticalSection(a) \
        WaitForSingleObject_stub((void*)a, CRITICAL_SECTION_TYPE)

#define ReleaseMutex(a) \
        ReleaseLock_stub((void*)a, MUTEX_LOCK_TYPE))

#define ReleaseSemaphore(a, b, c) \
        ReleaseLock_stub((void*)a, SEMAPHORE_LOCK_TYPE))

#define LeaveCriticalSection(a) \
        ReleaseLock_stub((void*)a, CRITICAL_SECTION_TYPE))
    然后,改写锁的申请函数,

  1. void WaitForSingleObject_stub(void* hLock, int type) 
  2.     /* step 1 */ 
  3.     WaitForSingleObject(hDbgLock); 
  4.     /* check if lock loops arounds threads */ 
  5.     ReleaseMutex(hDbgLock); 
  6.  
  7.     /* step 2 */ 
  8.     if(NORMAL_LOCK_TYPE == type) 
  9.         WaitForSingleObject((HANDLE)hLock, INFINITE); 
  10.     else if(CRITICAL_SECTION_TYPE == type) 
  11.         EnterCriticalSection((LPCRITICAL_SECTION)hLock); 
  12.     else 
  13.         assert(0); 
  14.  
  15.     /* step 3 */ 
  16.     WaitForSingleObject(hDbgLock); 
  17.     /* add lock to specified threadid list */ 
  18.     ReleaseMutex(hDbgLock); 
void WaitForSingleObject_stub(void* hLock, int type)
{
    /* step 1 */
    WaitForSingleObject(hDbgLock);
    /* check if lock loops arounds threads */
    ReleaseMutex(hDbgLock);

    /* step 2 */
    if(NORMAL_LOCK_TYPE == type)
        WaitForSingleObject((HANDLE)hLock, INFINITE);
    else if(CRITICAL_SECTION_TYPE == type)
        EnterCriticalSection((LPCRITICAL_SECTION)hLock);
    else
        assert(0);

    /* step 3 */
    WaitForSingleObject(hDbgLock);
    /* add lock to specified threadid list */
    ReleaseMutex(hDbgLock);
}
    最后,需要改写锁的释放函数。

  1. void ReleaseLock_stub(void* hLock, int type) 
  2.     /* step 1 */ 
  3.     WaitForSingleObject(hDbgLock); 
  4.     /* remove lock from specified threadid list */ 
  5.     ReleaseMutex(hDbgLock); 
  6.  
  7.     /* step 2 */ 
  8.     if(MUTEX_LOCK_TYPE))== type) 
  9.         ReleaseMutex(HANDLE)hLock); 
  10.     else if(SEMAPHORE_LOCK_TYPE == type) 
  11.         ReleaseSemaphore((HANDLE)hLock, 1, NULL); 
  12.     else if(CRITICAL_SECTION_TYPE == type) 
  13.         LeaveCriticalSection((LPCRITICAL_SECTION)hLock); 
  14.     assert(0); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值