Mutex
A mutex (short for mutual exclusion) is a synchronization object that can be used to protect a shared resource from concurrent access by multiple threads. Only one thread can own a mutex at any given time. If a thread attempts to acquire a mutex that is already owned, the thread will block until the mutex is released.
Key Concepts
- Ownership: A mutex has a single owner at any given time. When a thread acquires a mutex, it becomes the owner.
- Recursion: Mutexes can be recursive, meaning the owning thread can acquire the mutex multiple times. For each acquisition, a corresponding release is required.
- Priority Inversion: Mutexes can help mitigate priority inversion issues through mechanisms like priority boosting.
Common Use Cases
- Protecting shared data structures that are accessed by multiple threads.
- Ensuring that only one thread can execute a critical section of code at a time.
- Coordinating access to hardware devices or other shared resources.
Core API Functions
CreateMutex
Creates or opens a named or unnamed mutex object.
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
lpMutexAttributes: Security attributes.bInitialOwner: IfTRUE, the calling thread is granted initial ownership of the mutex.lpName: The name of the mutex object.
Returns a handle to the mutex object or NULL on failure.
OpenMutex
Opens an existing named mutex object.
HANDLE OpenMutex(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
dwDesiredAccess: Access rights.bInheritHandle: Whether the handle is inheritable.lpName: The name of the mutex object.
Returns a handle to the mutex object or NULL on failure.
ReleaseMutex
Releases ownership of the specified mutex object.
BOOL ReleaseMutex(
HANDLE hMutex
);
hMutex: A handle to the mutex object.
Returns TRUE on success, FALSE on failure.
WaitForSingleObject (and related functions)
Waits until the specified object is in the signaled state or the time-out interval elapses. This is used to acquire the mutex.
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
hHandle: A handle to the mutex object.dwMilliseconds: Time-out interval in milliseconds.
Returns WAIT_OBJECT_0 if the state is signaled, WAIT_TIMEOUT if the time-out expires, or WAIT_FAILED on error.
Example Usage
The following C++ snippet demonstrates how to use a mutex to protect a shared counter:
#include <windows.h>
#include <iostream>
HANDLE hMutex;
int sharedCounter = 0;
DWORD WINAPI ThreadProc(LPVOID lpParam) {
WaitForSingleObject(hMutex, INFINITE); // Acquire mutex
// Critical section
sharedCounter++;
std::cout << "Counter: " << sharedCounter << std::endl;
ReleaseMutex(hMutex); // Release mutex
return 0;
}
int main() {
hMutex = CreateMutex(NULL, FALSE, NULL); // Create a mutex
HANDLE hThread1 = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(hMutex);
return 0;
}