Поделиться через


Mutex Objects (Windows Embedded CE 6.0)

1/6/2010

A mutex object is a synchronization object whose state is set to signaled when it is not owned by a thread.

As its name implies, it coordinates mutually exclusive access to a shared resource.

Only one thread at a time can own a mutex object.

A thread calls the CreateMutex function to create a mutex object. The creating thread can request immediate ownership of the mutex object, as well as specify a name for the mutex object.

Threads in other processes can open a handle to an existing mutex object by specifying the object name in a call to CreateMutex. If a mutex object with that name already exists, GetLastError returns ERROR_ALREADY_EXISTS.

For more information about names for mutex objects and event objects, see Interprocess Synchronization.

Any thread with a handle to a mutex object can use a wait function 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 by calling the ReleaseMutex function.

The return value of the wait function indicates whether the function returned for some reason other than that the state of the mutex is set to signaled.

For more information about wait functions, see Wait Functions.

When a thread owns a mutex object, it can specify the same mutex object in repeated calls to one of the wait functions without blocking it. This prevents a thread from deadlocking itself while waiting for a mutex object that it already owns.

To release its ownership under such circumstances, the thread must call ReleaseMutex once for each time that the mutex object satisfied the conditions of a wait function.

A mutex object is considered abandoned if a thread terminates without releasing its ownership of a mutex object.

A waiting thread can acquire ownership of an abandoned mutex object, but the wait function 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 protected by the mutex object is in an undefined state.

If the thread proceeds as though the mutex object is not 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.

The following code example shows how to call CreateMutex to create a named mutex object:

void NamedMutexExample (void)
{
   HANDLE  hMutex;
   TCHAR szMsg[100];
   hMutex = CreateMutex (NULL, // No security descriptor
                         FALSE, // Mutex object not owned
                         TEXT("NameOfMutexObject")); // Object name
      if (NULL == hMutex)
         {
            // Your code to deal with the error goes here.
            // Here is one example of what might be done.
            wsprintf (szMsg, TEXT("CreateMutex error: %d."), GetLastError ());
            MessageBox (NULL, szMsg, TEXT("Error"), MB_OK);
         }
      else
         {
            // Not an error: deal with success
            if ( ERROR_ALREADY_EXISTS == GetLastError () )
               MessageBox (NULL, TEXT("CreateMutex opened existing mutex."), TEXT("Results"), MB_OK);
           else
              MessageBox (NULL, TEXT("CreateMutex created new mutex."), TEXT("Results"), MB_OK);
         }
      }
   }
}

The following code example opens a handle of a mutex object. It also uses 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 runs no matter how the try block terminates, unless the try block includes a call to the TerminateThread function.

BOOL WriteToDatabase (HANDLE hMutex)
{
   DWORD dwWaitResult;
   dwWaitResult = WaitForSingleObject (hMutex, // Handle of mutex object
   5000L); // Five-second time-out
   switch (dwWaitResult)
   {
      case WAIT_OBJECT_0:
      __try
      {
         // Your code to write to the database goes here.
      }
   __finally
      {
         // Your code to clean up the database operations goes here.
         if (! ReleaseMutex (hMutex))
            {
               // Your code to deal with the error goes here.
            }
         }
      break;
      // Cannot get mutex object ownership due to time-out
      case WAIT_TIMEOUT:
      return FALSE;
      // Got ownership of an abandoned mutex object
      case WAIT_ABANDONED:
      return FALSE;
   }
   return TRUE;
}

See Also

Concepts

Synchronization