Mutexes

This sample program demonstrates how to use mutexes (i.e. locks) in Windows.  This program uses three mutex calls:  CreateMutex to create a mutex, WaitForSingleObject to acquire the mutex, and ReleaseMutex to release the mutex.

This program creates a mutex, and then it creates four threads that try to acquire this mutex.  Once a thread has acquired the mutex, it waits for five seconds before releasing it.  The main thread waits for all of the threads to exit before it exits.  Here are the MSVC++ project and executable for this program.

The output of this program is:

Thread ONE trying to acquire the mutex.
  Thread ONE has acquired the mutex.
Thread TWO trying to acquire the mutex.
Thread THREE trying to acquire the mutex.
Thread FOUR trying to acquire the mutex.
    Thread ONE about to release the mutex.
  Thread FOUR has acquired the mutex.
    Thread FOUR about to release the mutex.
  Thread TWO has acquired the mutex.
    Thread TWO about to release the mutex.
  Thread THREE has acquired the mutex.
    Thread THREE about to release the mutex.

All threads have exited.  Press Enter to continue.

mutexExample.cpp:

#include <windows.h>
#include <stdio.h>
#include <assert.h>

HANDLE mutex = NULL;


//
// Acquire the mutex, wait for 5 seconds, release the mutex, and then exit.
//
unsigned long __stdcall
MutexThread( void * threadName )
{
    BOOL success;
    DWORD retVal;

    char * str = (char *)threadName;

    //
    // Acquire the mutex.    
    //
    printf( "Thread %s trying to acquire the mutex.\n", threadName );
    retVal = WaitForSingleObject( mutex, INFINITE );
    assert( retVal == WAIT_OBJECT_0 ); // always check for success

    printf( "  Thread %s has acquired the mutex.\n", threadName );

    //
    // Sleep for 5 seconds.
    //
    Sleep( 5000 );

    //
    // Release the mutex.
    //
    printf( "    Thread %s about to release the mutex.\n", threadName );
    success = ReleaseMutex( mutex );
    assert( success );  // always check for success
    

    return 0;
}


//
// Main
//
void
main()
{
    DWORD threadID;
    DWORD retVal;
    HANDLE threadHandles[4];

    //
    // Create the mutex
    //
    mutex = CreateMutex( NULL,  // no security attributes 
                         FALSE, // this thread is not the initial owner
                         NULL   // no name
                        );
    assert( mutex != NULL );  // always check for success

    //
    // Create four threads that will all try to acquire mutex.
    //
    threadHandles[0] = CreateThread( NULL, 0, MutexThread, (void*)"ONE", 0, &threadID );
    assert( threadHandles[0] != NULL );  // always check for success

    threadHandles[1] = CreateThread( NULL, 0, MutexThread, (void*)"TWO", 0, &threadID );
    assert( threadHandles[1] != NULL );  // always check for success

    threadHandles[2] = CreateThread( NULL, 0, MutexThread, (void*)"THREE", 0, &threadID );
    assert( threadHandles[2] != NULL );  // always check for success

    threadHandles[3] = CreateThread( NULL, 0, MutexThread, (void*)"FOUR", 0, &threadID );
    assert( threadHandles[3] != NULL );  // always check for success



    //
    // WaitForMultipleObjects can accept at most MAXIMUM_WAIT_OBJECTS objects.
    //
    int numThreads = 4;
    assert( numThreads <= MAXIMUM_WAIT_OBJECTS );

    //
    // Wait for the four threads to finish
    //
    retVal = WaitForMultipleObjects( numThreads,    // number of threads to wait for 
                                     threadHandles, // handles for threads to wait for
                                     TRUE,          // wait for all of the threads
                                     INFINITE       // wait forever
                                    );

    //
    // If successful, WaitForMultipleObjects returns a value between
    // WAIT_OBJECT_0 and ( WAIT_OBJECT_0 + numThreads - 1).  
    //
    // This assert checks if the function was successful.
    //
    assert( ( retVal >= WAIT_OBJECT_0 ) && ( retVal <= ( WAIT_OBJECT_0 + numThreads - 1 ) ) );

    printf( "\nAll threads have exited.  Press Enter to continue.\n" );
    getchar();

}