Windows Thread Synchronization 20

 

 

 

Using Mutex Objects Program Example

 

You can use a mutex object to protect a shared resource from simultaneous access by multiple threads or processes. Each thread must wait for ownership of the mutex before it can execute the code that accesses the shared resource. For example, if several threads share access to a database, the threads can use a mutex object to permit only one thread at a time to write to the database. The following example uses the CreateMutex() function to create a mutex object and the CreateThread() function to create worker threads. When a thread of this process writes to the database, it first requests ownership of the mutex using the WaitForSingleObject() function. If the thread obtains ownership of the mutex, it writes to the database and then releases its ownership of the mutex using the ReleaseMutex() function. This example uses structured exception handling to ensure that the thread properly releases the mutex object. The __finally block of code is executed no matter how the __try block terminates (unless the __try block includes a call to the TerminateThread() function). This prevents the mutex object from being abandoned inadvertently. If a mutex is abandoned, the thread that owned the mutex did not properly release it before terminating. In this case, the status of the shared resource is indeterminate, and continuing to use the mutex can obscure a potentially serious error. Some applications might attempt to restore the resource to a consistent state; this example simply returns an error and stops using the mutex.

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

 

Using Mutex Objects Program Example: Creating new Win32 empty cosnsole application project in Visual C++

 

 

Then, add the source file and give it a suitable name.

 

Using Mutex Objects Program Example: Adding new C++ source file to the existing Win32 project

 

Next, add the following source code.

 

#include <windows.h>

#include <stdio.h>

 

#define THREADCOUNT 2

 

HANDLE ghMutex;

 

DWORD WINAPI WriteToDatabase(LPVOID);

 

void wmain()

{

    HANDLE aThread[THREADCOUNT];

    DWORD ThreadID;

    int i;

      DWORD Ret;

 

    // Create a mutex with no initial owner

    ghMutex = CreateMutex(

        NULL,              // default security attributes

        FALSE,           // initially not owned

        NULL);             // unnamed mutex

 

    if (ghMutex == NULL)

    {

        wprintf(LCreateMutex() failed, error %d\n, GetLastError());

        return;

    }

      else

            wprintf(LCreateMutex() is Ok\n);

 

    // Create worker threads

    wprintf(LCreating the worker threads...\n);

    for( i=0; i < THREADCOUNT; i++ )

    {

        aThread[i] = CreateThread(

                     NULL,       // default security attributes

                     0,          // default stack size

                     (LPTHREAD_START_ROUTINE) WriteToDatabase,

                     NULL,       // no thread function arguments

                     0,          // default creation flags

                     &ThreadID); // receive thread identifier

 

        if( aThread[i] == NULL )

        {

            wprintf(LCreateThread() failed, error: %d\n, GetLastError());

            return;

        }

            else

                  wprintf(LCreateThread() #%i is OK\n, i);

    }

 

    // Wait for all threads to terminate

    // WAIT_OBJECT_0, WAIT_ABANDONED_0, WAIT_TIMEOUT, WAIT_FAILED

    Ret = WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

    wprintf(LWaitForMultipleObjects() return value is %d\n, Ret);

 

    // Close thread and mutex handles

    for( i=0; i < THREADCOUNT; i++ )

      {

        if(CloseHandle(aThread[i]) != 0)

                  wprintf(LThread %d handle was successfully closed...\n, GetCurrentThreadId());

            else

                  wprintf(LFailed to close thread %d handle...\n, GetCurrentThreadId());

      }

 

    CloseHandle(ghMutex);

}

 

DWORD WINAPI WriteToDatabase(LPVOID lpParam )

{

    DWORD dwCount=0, dwWaitResult;

 

    // Request ownership of mutex.

    while( dwCount < 20 )

    {

        dwWaitResult = WaitForSingleObject(

            ghMutex,    // handle to mutex

            INFINITE);  // no time-out interval

 

        switch (dwWaitResult)

        {

            // The thread got ownership of the mutex

            case WAIT_OBJECT_0:

                __try {

                    // TODO: Write to the database

                    wprintf(LThread %d writing to database, count #%d\n, GetCurrentThreadId(), dwCount);

                    dwCount++;

                }

 

                __finally {

                    // Release ownership of the mutex object

                    if (! ReleaseMutex(ghMutex))

                    {

                        // Handle error.

                    }

                }

                break;

 

            // The thread got ownership of an abandoned mutex

            // The database is in an indeterminate state

            case WAIT_ABANDONED:

                return FALSE;

        }

    }

    return TRUE;

}

 

Build and run the project. The following screenshot is a sample output.

 

Using Mutex Objects Program Example: A sample of console program output

 

 

 

< Thread Synchronization 19 | Thread Synchronization Programming | Win32 Programming | Thread Synchronization 21 >