suspend造成死锁的例子和原因分析

 

今天loris分享了一个关于使用suspend造成死锁的例子,部分代码如下:

UINT AFX_CDECL ThreadTest(LPVOID pvParam) { while (TRUE) { HMODULE hHandle = ::LoadLibrary("Common.dll"); if (hHandle) { void *pFun = (void *)::GetProcAddress(hHandle, "doSomething"); ::FreeLibrary(hHandle); } ::Sleep(10); } } void CTESTWIN2Dlg::OnOK() { CWinThread *pThread = AfxBeginThread(ThreadTest, (LPVOID)this, 0, 0, CREATE_SUSPENDED); ::DuplicateHandle(::GetCurrentProcess(), pThread->m_hThread, ::GetCurrentProcess(), &m_hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); pThread->ResumeThread(); m_bIsRun = TRUE; SetTimer(10, 10, NULL); } void CTESTWIN2Dlg::OnTimer(UINT nIDEvent) { if (m_bIsRun) { ::SuspendThread(m_hThread); m_bIsRun = FALSE; HMODULE hHandle = ::LoadLibrary("TSVul.dat"); if (hHandle) { void *pFun = (void *)::GetProcAddress(hHandle, "MyDoSome"); ::FreeLibrary(hHandle); } } else { ::ResumeThread(m_hThread); m_bIsRun = TRUE; } CDialog::OnTimer(nIDEvent); }

 

win32下的API基本都是线程安全的,因此API里面有很多线程同步的地方,LoadLibrary里面有一个临界区,线程函数在执行到LoadLibrary里面之后,如果刚好走到LoadLibrary的临界区里面,此时主线程的ontimer触发,将该线程挂起,ontimer继续执行,运行到LoadLibrary后,由于线程中LoadLibrary还没有从临界区出来,此时就造成主线程ontimer里面的LoadLibrary无限等待,主线程挂起。

因此不建议用suspend暂停线程,MSDN也有说明,suspend最好只在debug里面使用。

那怎么使线程挂起呢?可以使用事件等方式,用wait族函数来暂停线程。

 

【END】

你可能感兴趣的:(C++,Win32)