windows multithreading CreateMutex

30 Views Asked by At

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

1

There are 1 best solutions below

0
Adrian McCarthy On

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.