c-使用互斥锁来锁定对列表对象的所有访问



我想创建一些代码,允许创建一个支持多线程操作的列表。我的想法很简单:每当线程想要对列表进行操作时,它都应该调用LockList(),当它完成时,它应该调用UnlockList()。通过这样做,其他线程对锁定对象的任何其他api调用都将导致失败,并且只有所有者线程才能使用该对象。

我测试了它,令人惊讶的是,我没有崩溃,但相反,在所有线程都将完成对列表的操作后,在清理时LockList()只失败一次,然后一切都如预期那样工作。

以下是LockList()UnlockList()函数的定义:

WINBOOL APIENTRY LockList (HANDLE hList)
{
#define lpList ((LPLIST_INFO)hList)
DWORD dwState = WaitForSingleObject(lpList->hMutex, 0);
if(dwState != WAIT_OBJECT_0)
return FALSE;
return TRUE;
#undef lpList
}
WINBOOL APIENTRY UnlockList (HANDLE hList)
{
#define lpList ((LPLIST_INFO)hList)
DWORD dwState = WaitForSingleObject(lpList->hMutex, 0);
if(dwState != WAIT_OBJECT_0)
return FALSE;
ReleaseMutex(lpList->hMutex);
return TRUE;
#undef lpList
}

我尝试通过让一些线程在列表中插入项目来测试我的代码,更具体地说,我制作了一个Students列表。这是代码的重要部分:

DWORD APIENTRY ThreadProc(LPVOID lpvList)
{
#define hList ((HANDLE)lpvList)
for(DWORD I = 0; I < 1000; I++)
{
// wait until the thread gets ownership of the mutex ...
while(!LockList(hList)); 
// Insert the entity into the list ...
UnlockList(hList);
}
RETURN 0;
#undef hList
}
#define WORKER_COUNT 40
INT WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
// An anonymous mutex is created with bInitialOwner FALSE
HANDLE hList = CreateList(GetProcessHeap(), 0, StudentConstructor, StudentDestructor);
if(hList == NULL)
return MessageBoxA(HWND_DESKTOP, "Could not create list.", "Runtime Error", MB_OK|MB_ICONERROR);
HANDLE hThreads[WORKER_COUNT];
DWORD dwThreadIds[WORKER_COUNT];
for(DWORD I = 0; I < WORKER_COUNT; I++)
{
hThreads[I] = CreateThread(NULL, 0, ThreadProc, hList, 0, &dwThreadIds[I]);
if(hThreads[I] == NULL)
return MessageBoxA(HWND_DESKTOP, "Could not create worker thread.", "Runtime Error", MB_OK|MB_ICONERROR);
}
WaitForMultipleObjects(WORKER_COUNT, hThreads, TRUE, INFINITE);
for(DWORD I = 0; I < WORKER_COUNT; I++)
CloseHandle(hThreads[I]);
while(!LockList(hList))
printf("Could not get ownership of the list.n");
printf("The list has %lu entities.n", GetListEntityCount(hList));
if(!DeleteList(hList))
return MessageBoxA(HWND_DESKTOP, "Could not delete list.", "Runtime Error", MB_OK|MB_ICONERROR);
return 0;
}

还值得一提的是,在所有api调用中进行的检查如下所示:

// ...
DWORD dwState = WaitForSingleObject(lpList->hMutex, 0);
if(dwState != WAIT_OBJECT_0)
return FALSE; // or NULL or whatever signals failure.
// ...

我是否正确使用WaitForSingleObject()?为什么LockList()失败一次(在主线程中(,即使所有线程都释放了互斥体的所有权?

您的锁定/解锁语义不平衡。

互斥句柄上对WaitForSingleObject的每次调用都需要与对ReleaseMutex的调用配对(windows互斥对象允许同一线程进行多次获取(。

现在,如果你有锁定列表(hList(;解锁列表(hList(;

这意味着:等待线程结束等待线程结束释放Mutex

最新更新