Mutex)
Mutex represents a mutex data structure and is also used as a binary signal lamp. A mutex is basically a multi-task sensitive binary signal. It can be used for synchronizing multiple tasks. It is often used to protect critical code segments from interruptions and share resources for synchronization.
Mutex is essentially a lock that provides exclusive access to resources. Therefore, mutex is mainly used for mutex. The value of the mutex object. Only values 0 and 1 are supported. These two values also represent the mutex status. The value 0 indicates the lock status. The current object is locked. If a user's process/thread attempts to lock critical resources, it enters the waiting queue. The value 1 indicates the idle status, the current object is idle, and the user process/thread can lock critical resources. After that, the mutex value is reduced by 1 to 0.
Mutex can be abstracted into four operations:
-Create
-Lock
-Unlock unlock
-Destroy destroy
A mutex can have an initial value when it is created, indicating whether the mutex is locked or idle after it is created. In the same thread, to prevent deadlocks, the system does not allow two consecutive mutex locks (the system usually returns immediately after the second call ). That is to say, the lock and unlock operations must be completed in the same thread.
Mutex functions provided by different operating systems:
Action/System |
Win32 |
Linyx |
Solaris |
Create |
Createmutex |
Pthread_mutex_init |
Mutex_init |
Lock |
Waitforsingleobject |
Pthread_mutex_lock |
Mutex_lock |
Unlock |
Releasemutex |
Pthread_mutex_unlock |
Mutex_unlock |
Destroy |
Closehandle |
Pthread_mutex_destroy |
Mutex_destroy |
A deadlock occurs when multiple dependency locks exist, and occurs when a thread tries to lock the mutex in the reverse order of the other thread. It is important to avoid a deadlock when mutex is used.
In general, there are several unwritten basic principles:
You must obtain the lock before performing operations on shared resources.
The lock must be released after the operation is completed.
Use the lock as soon as possible.
If there are multiple locks, for example, if the order of acquisition is ABC, the release order should also be ABC.
When a thread returns an error, it should release the lock it obtained.
Readers may wonder how to implement the "pending wait" and "wake up the waiting thread" operations? Each mutex has a waiting queue. A thread must wait for a pause on mutex. First, add itself to the waiting queue and set the thread status to sleep, then, call the scheduler function to switch to another thread. To wake up other threads in the waiting queue, you only need to extract one thread from the waiting queue, change its status from sleep to ready, and add it to the ready queue, the next time the scheduler executes the function, it is possible to switch to the wake-up thread.
Generally, if the same thread calls lock twice, the thread will suspend waiting for other threads to release the lock because the lock has been occupied for the second call, however, the lock is occupied by itself, and the thread is suspended and has no chance to release the lock, so it is always in the pending state. This is called a deadlock ). Another typical deadlock situation is as follows: thread a acquires lock 1 and thread B acquires lock 2. Then thread a calls lock to attempt to obtain lock 2, the result is that thread B needs to suspend wait for thread B to release lock 2, and thread B also calls lock to try to obtain lock 1. The result is that thread B needs to suspend wait for thread a to release lock 1, so thread a and thread B are always suspended. It is hard to imagine if more threads and more locks are involved, the possibility of deadlock will become complicated and difficult to judge.
Semaphores
Semaphore (semaphore) is a facility used in a multi-threaded environment. It coordinates various threads to ensure that they can properly and reasonably use public resources.
Semaphores can be divided into several types:
2. binary semaphore: only 0 or 1 values can be obtained by one thread.
Integer semaphore: the semaphore value is an integer, which can be obtained by multiple threads at the same time until the semaphore value changes to 0.
2. Record semaphore: in addition to an integer value (count), each semaphore s also has a waiting queue list, which is the identifier of each thread blocking the semaphore. When a semaphore is released and the value is incremented, the system automatically wakes up a waiting thread from the waiting queue to obtain the semaphore. At the same time, the semaphore is reduced by one.
A semaphore controls access to shared resources through a counter. The semaphore value is a non-negative integer, and all threads passing through it will subtract this integer by one. If the counter is greater than 0, access is allowed, and the counter is reduced by 1. If it is 0, access is forbidden, and all threads trying to pass it will be in the waiting state.
The result of counter calculation is a pass that allows access to shared resources. Therefore, to access shared resources, the thread must obtain a pass from the semaphore. If the count of the semaphore is greater than 0, the thread obtains a pass, which will result in a decrease in the count of the semaphore. Otherwise, this thread will be blocked until a pass is obtained. When this thread no longer needs to access shared resources, it releases the pass, which causes the Count of semaphores to increase. If another thread waits for the pass, that thread will get the pass at that time.
Semaphore can be abstracted into five operations:
-Create
-Wait for wait:
The thread waits for the semaphore. If the value is greater than 0, the value is obtained. If the value is equal to 0, the thread enters the sleep state until the value of the signal is greater than 0 or times out.
-Release post
Execute the release semaphores, then add one; if there is a waiting thread at this time, wake up the thread.
-Try to wait for trywait
If trywait is called, the thread does not actually obtain the semaphore, or checks whether the semaphore can be obtained. If the signal value is greater than 0, trywait returns success; otherwise, return failure.
-Destroy destroy
Semaphores can be used to protect two or more key code segments that cannot be concurrently called. Before entering a key code segment, the thread must obtain a semaphore. If no thread exists in the key code segment, the thread immediately enters the part in the block. Once the key code segment is complete, the thread must release the semaphore. Other threads that want to enter the key code segment must wait until the first thread releases the semaphore. To complete this process, you need to create a semaphore and place acquire semaphore VI and release semaphore VI at the beginning and end of each key code segment respectively. Make sure that these semaphores VI reference the initial semaphores.
Action/System |
Win32 |
POSIX |
Create |
Createsemaphore |
Sem_init |
Wait |
Waitforsingleobject |
SEM _ Wait |
Release |
Releasemutex |
SEM _ post |
Trying to wait |
Waitforsingleobject |
SEM _ trywait |
Destroy |
Closehandle |
Sem_destroy |
(Producer and consumer)
Differences between mutex and semaphore
1. The mutex is used for thread mutex, and the signal line is used for thread synchronization.
This is the fundamental difference between mutex and semaphore, that is, the difference between mutex and synchronization.
Mutual Exclusion: A Resource allows only one visitor to access it at the same time, which is unique and exclusive. However, mutual exclusion cannot limit the access sequence of visitors to resources, that is, access is out of order.
Synchronization: on the basis of mutual exclusion (in most cases), visitors can access resources in an orderly manner through other mechanisms. In most cases, synchronization has implemented mutex, especially when all resources are written. In rare cases, multiple visitors are allowed to access resources at the same time.
2. The mutex value can only be 0/1, and the signal value can be a non-negative integer.
That is to say, a mutex can only be used for mutex access to one resource. It cannot implement multi-thread mutex problem for multiple resources. Semaphores can achieve multi-thread mutex and synchronization of multiple similar resources. When the semaphores are single-value semaphores, mutual access to a resource can also be completed.
3.The lock and unlock of mutex must be used by the same thread, and the semaphore can be released by one thread and the other.
Mutex and semaphore