A mutex object is a synchronization object whose state is set to signaled when it is not owned by any thread, and nonsignaled when it is owned. Its name comes from its usefulness in coordinating mutually-exclusive access to a shared resource. Only one thread at a time can own a mutex object. For example, to prevent two threads from writing to shared memory at the same time, each thread waits for ownership of a mutex object before executing the code that accesses the memory. After writing to the shared memory, the thread releases the mutex object.
A thread uses the CreateMutex function to create a mutex object. The creating thread can request immediate ownership of the mutex object and can also specify a name for the mutex object. Threads in other processes can open a handle to an existing mutex object by specifying its name in a call to CreateMutex. For additional information about names for mutex and event objects, see Interprocess Synchronization.
Any thread with a handle of a mutex object can use one of the wait functions to request ownership of the mutex object. If the mutex object is owned by another thread, the wait function blocks the requesting thread until the owning thread releases the mutex object using the ReleaseMutex function. The return value of the wait function indicates whether the function returned for some reason other than the state of the mutex being set to signaled.
Once a thread owns a mutex, it can specify the same mutex in repeated calls to one of the wait functions without blocking its execution. This prevents a thread from deadlocking itself while waiting for a mutex that it already owns. To release its ownership under such circumstances, the thread must call ReleaseMutex once for each time that the mutex satisfied the conditions of a wait function.
If a thread terminates without releasing its ownership of a mutex object, the mutex object is considered to be abandoned. A waiting thread can acquire ownership of an abandoned mutex object, but the wait function's return value indicates that the mutex object is abandoned. To be safe, assume that an abandoned mutex object indicates that an error has occurred and that any shared resource being protected by the mutex object is in an undefined state. If the thread proceeds as though the mutex object had not been abandoned, the object's abandoned flag is cleared when the thread releases its ownership. This restores typical behavior, if a handle to the mutex object is subsequently specified in a wait function.
In the following code examples, a process uses the CreateMutex function first to create a named mutex object, and in the second piece of code, to open a handle of an existing mutex object. Additionally, it uses structured exception-handling to ensure that the thread properly releases the mutex object.
HANDLE hMutex;
hMutex = CreateMutex
(
NULL, // no security attributes
FALSE, // initially not owned
"MutexToProtectDatabase"); // name of mutex
if (hMutex == NULL)
{
// Check for error.
}
When a thread of this process writes to the database, it first requests ownership of the mutex. If it gets ownership, the thread writes to the database and then releases its ownership.
The example uses the try-finally structured exception-handling syntax to ensure that the thread properly releases the mutex object. To prevent the mutex object from being abandoned inadvertently, 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.
BOOL FunctionToWriteToDatabase(HANDLE hMutex)
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject(
hMutex, // handle of mutex
5000L); // five-second time-out interval
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
try
{
// Write to the database.
}
finally
{
if (! ReleaseMutex(hMutex))
{
// Deal with error.
}
break;
}
// Cannot get mutex ownership due to time-out.
case WAIT_TIMEOUT:
return FALSE;
// Got ownership of the abandoned mutex object.
case WAIT_ABANDONED:
return FALSE;
}
return TRUE;
}