. Thread Access Mechanism
There are two kinds of relationship between tasks: 1, indirect relationship, 2, direct relationship.
For example 1. Task A writes to the MO buffer. Task B reads from this buffer. Then the relationship between A and B is a direct relationship, so the mechanism to achieve this direct relationship is to synchronize
2. Task A To use the printer, Task B also uses the printer, so the relationship between A and B is indirect only if the printer is used at the end of task A. Then the mechanism to achieve this indirect relationship is mutually exclusive.
The main mechanisms for implementing mutual exclusion and synchronization between threads in Linux are: Semaphores and mutexes
Mutual exclusion Lock
A mutex is a simple lock-in method to control access to shared resources. There are only two states of this mutex, that is, locking and unlocking.
You can think of a mutex as a global variable in a sense. Only one thread can hold a lock on a mutex at the same time, and a locked thread can manipulate the shared resource. If another thread wants to lock a locked mutex, the thread hangs until the locked thread releases the mutex. It can be said that this mutex allows shared resources to be manipulated sequentially in each thread.
The operation of the mutex mainly consists of the following steps.
Mutex initialization: Pthread_mutex_init
Mutex Lock: Pthread_mutex_lock
Lock Mutex: Pthread_mutex_trylock
Mutex Lock: Pthread_mutex_unlock
Eliminate mutex: Pthread_mutex_destroy
Among them, the mutex can be divided into fast mutex, recursive mutex and error-checking mutex. The difference between the three types of locks is primarily the need for blocking waits for other threads that do not occupy the mutex when they want the mutex to be locked.
A quick lock is a call thread that blocks until the line threads unlocked that owns the mutex.
A recursive mutex can successfully return and increase the number of times the calling thread locks on the mutex, whereas a fault-checking mutex is a non-blocking version of a fast mutex that returns immediately and returns an error message.
int Pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)//Mutex initialization function
Mutexattr = Pthread_mutex_initializer: Creates a quick mutex, which means that the calling thread blocks until the line threads unlocked that owns the mutex
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: Create recursive function incoming value mutexattr Mutex, recursive mutex can successfully return and increase the number of times the calling thread locks on the mutex
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: Creates a fault-checking mutex, and the error-checking mutex is a non-blocking version of the fast mutex.
int Pthread_mutex_lock (pthread_mutex_t *mutex,)//Mutex lock
int Pthread_mutex_trylock (pthread_mutex_t *mutex,)//mutex to determine lock
int Pthread_mutex_unlock (pthread_mutex_t *mutex,)//Mutex lock
int Pthread_mutex_destroy (pthread_mutex_t *mutex,)//elimination Mutex
In all thread synchronization methods, the exit rate of the mutex (mutex) is probably much higher than the other method. The
mutex can be divided into recursive locks (recursive mutexes) and non-recursive locks (non-recursive mutexes). A recursive lock can also be called a reentrant lock (reentrant mutex), and a
non-recursive lock is called an non-reentrant mutex. The only difference between the
is that the same thread can get the same recursive lock multiple times, without creating a deadlock. If a thread acquires the same non-recursive lock multiple times, a deadlock occurs. The mutex and critical section under
Windows is recursive. pthread_mutex_t locks under Linux are non-recursive by default. The
can display the settings of the Pthread_mutex_recursive property and set pthread_mutex_t as a recursive lock.
However, if you misuse these two locks, it is likely to cause a deadlock in the program.
Mutexlock mutex;
void F1 ()
{
Mutex.lock (); //do something
mutex.unlock ();
}
void F2 ()
{
Mutex.lock (); //do something
F1 ();
mutex.unlock ();
}
Both the F1 function and the F2 function acquire the same lock, and the F2 function calls the F1 function. If the Mutexlock lock is a non-recursive lock, the program will deadlock immediately.
Therefore, it is very important to be cautious when locking a program, or it is easy to create deadlocks because of this invocation relationship.
However, this does not mean that a recursive lock should be used instead of a non-recursive lock. Recursive locks are easy to use, but often hide some code problems.
For example, calling a function and the called function to get a lock, all modifying the same object, is prone to problems. Therefore, in cases where a non-recursive lock can be used,
You should use non-recursive locks as much as possible, because deadlocks are relatively easy to find by debugging.
Mutex Lock Notes