多线程的那点儿事12(之避免死锁)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
预防死锁的注意事项:
(1)在编写多线程程序之前,首先编写正确的程序,然后再移植到多线程
(2)时刻检查自己写的程序有没有在跳出时忘记释放锁
(3)如果自己的模块可能重复使用一个锁,建议使用嵌套锁
(4)对于某些锁代码,不要临时重新编写,建议使用库里面的锁,或者自己曾经编写的锁
(5)如果某项业务需要获取多个锁,必须保证锁的按某种顺序获取,否则必定死锁
(6)编写简单的测试用例,验证有没有死锁
(7)编写验证死锁的程序,从源头避免死锁
首先,定义基本的数据结构和宏,
- 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))
然后,改写锁的申请函数,
- 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);
- }
最后,需要改写锁的释放函数。
- void ReleaseLock_stub(void* hLock, int type)
- {
- /* step 1 */
- WaitForSingleObject(hDbgLock);
- /* remove lock from specified threadid list */
- ReleaseMutex(hDbgLock);
- /* step 2 */
- if(MUTEX_LOCK_TYPE))== type)
- ReleaseMutex(HANDLE)hLock);
- else if(SEMAPHORE_LOCK_TYPE == type)
- ReleaseSemaphore((HANDLE)hLock, 1, NULL);
- else if(CRITICAL_SECTION_TYPE == type)
- LeaveCriticalSection((LPCRITICAL_SECTION)hLock);
- assert(0);
- }