Mutex and Semaphore
A mutex works like a critical section. You can think of a mutex as a lock that must be grabbed before execution can continue. Here is an example of three threads that all want access to a shared resource.
Each of the three threads tries to grab the mutex, but only one thread will be successful.
During the time that a thread holds the mutex, all other threads waiting on the mutex sleep. This behavior is very similar to that of a critical section.
Once a thread has finished using the shared resource, it releases the mutex. Another thread then can wakes up and grab the mutex.
A semaphore is a mutex that multiple threads can access. It’s like having multiple tokens. If only one token is available (others have been used), then semaphore is a mutex.
Though available for other uses, the following objects can also be used for synchronization.
Object |
Description |
Change notification |
Created by the FindFirstChangeNotification() function, its state is set to signaled when a specified type of change occurs within a specified directory or directory tree. |
Console input |
Created when a console is created. The handle to console input is returned by the CreateFile() function when CONIN$ is specified, or by the GetStdHandle() function. Its state is set to signaled when there is unread input in the console's input buffer, and set to nonsignaled when the input buffer is empty. |
Job |
Created by calling the CreateJobObject() function. The state of a job object is set to signaled when all its processes are terminated because the specified end-of-job time limit has been exceeded. |
Memory resource notification |
Created by the CreateMemoryResourceNotification() function. Its state is set to signaled when a specified type of change occurs within physical memory. |
Process |
Created by calling the CreateProcess() function. Its state is set to nonsignaled while the process is running, and set to signaled when the process terminates. |
Thread |
Created when a new thread is created by calling the CreateProcess(), CreateThread(), or CreateRemoteThread() function. Its state is set to nonsignaled while the thread is running, and set to signaled when the thread terminates. |
In some circumstances, you can also use a file, named pipe, or communications device as a synchronization object; however, their use for this purpose is discouraged. Instead, use asynchronous I/O and wait on the event object set in the OVERLAPPED structure. It is safer to use the event object because of the confusion that can occur when multiple simultaneous overlapped operations are performed on the same file, named pipe, or communications device. In this situation, there is no way to know which operation caused the object's state to be signaled.