The following c code, which is trying to synchronize each thread with a mutual exclusion lock, adds one to the variable g_Count, and eventually g_Count=THREAD_NUM. but for some reason, the variable g_Count is always less than the total number of threads?
#include <windows.h>
#include <stdio.h>
const unsigned int THREAD_NUM = 100;
unsigned int g_Count = 0;
HANDLE g_Mutex;
DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
HANDLE hThread[THREAD_NUM];
g_Mutex = CreateMutex(NULL, FALSE, NULL);
for (int i = 0; i < THREAD_NUM; i++)
{
hThread[i] = CreateThread(NULL, 0, ThreadFunc, &i, 0, NULL);
}
WaitForMultipleObjects(THREAD_NUM, hThread, TRUE, INFINITE);
for(int i=0; i < THREAD_NUM; i++ )
CloseHandle(hThread[i]);
CloseHandle(g_Mutex);
printf("%d", g_Count);
return 0;
}
DWORD WINAPI ThreadFunc(LPVOID p)
{
DWORD result;
result = WaitForSingleObject(g_Mutex, INFINITE);
if (result == WAIT_OBJECT_0)
{
g_Count++;
printf("Thread %d plus 1 to g_Count.\n", GetCurrentThreadId());
ReleaseMutex(g_Mutex);
}
return 0;
}
it outputs like:
Thread 27084 plus 1 to g_Count. Thread 18916 plus 1 to g_Count. Thread 12236 plus 1 to g_Count. 3
WaitForMultipleObjects is failing. It returns -1 and the last error is ERROR_INVALID_PARAMETER.
Some of the threads managed to increment the count before all threads were created.
Once WaitForMultipleObjects fails, the program closes the mutex handle. A few threads manage to call WaitForSingleObject on the mutex after it's been closed. Those calls fail with ERROR_INVALID_HANDLE. There are probably more threads that didn't even get that far, but the program ends and they're terminated as part of process cleanup.
So why does WaitForMultipleObjects fail? Because there's a limit on the number of handles it can wait on. That number is MAXIMUM_WAIT_OBJECTS, which appears to be 64.
If you change THREAD_NUM to MAXIMUM_WAIT_OBJECTS, it works as you intended. That said, you should always be checking the return values from CreateThread, WaitForMultipleObjects, and WaitForSingleObject because there are other things that can go wrong.