First, mutual exclusion lock
Mutex is essentially a lock that provides protected access to shared resources.
1. Initialization:
Under Linux, the thread's mutex data type is pthread_mutex_t. To initialize it before using it:
For a statically assigned mutex, you can set it to PTHREAD_MUTEX_INITIALIZER, or call pthread_mutex_init.
For dynamically allocated mutex, after applying for memory (malloc), initialize with pthread_mutex_init, and call pthread_mutex_destroy before freeing memory (free).
prototype:
Int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr);
Int pthread_mutex_destroy(pthread_mutex_t *mutex);
head File:
Return Value: Returns 0 if successful, and returns the error number if an error occurs.
Note: If you initialize the mutex with the default properties, simply set attr to NULL. Other values ​​are explained later.
2. Mutually exclusive operations:
For access to shared resources, the mutex is locked. If the mutex is locked, the calling thread blocks until the mutex is unlocked. After the access to the shared resource is completed, the mutex is mutex. The amount is unlocked.
First let's talk about the lock function:
head File:
prototype:
Int pthread_mutex_lock(pthread_mutex_t *mutex);
Int pthread_mutex_trylock(pthread_mutex_t *mutex);
Return Value: Returns 0 if successful, and returns the error number if an error occurs.
Description: Specifically, the trylock function, this function is a non-blocking call mode, that is, if the mutex is not locked, the trylock function will lock the mutex and gain access to the shared resource; The amount is locked, the trylock function will not block the wait and return directly to EBUSY, indicating that the shared resource is busy.
Let me talk about the solution function:
head File:
prototype:
Int pthread_mutex_unlock(pthread_mutex_t *mutex);
Return Value: Returns 0 if successful, and returns the error number if an error occurs.
3. Deadlock:
Deadlocks occur primarily when there are multiple dependencies latched, which occurs when one thread tries to lock the mutex in the reverse order of another thread. How to avoid deadlocks is something that should be taken care of when using mutex.
In general, there are several unwritten basic principles:
Be sure to obtain a lock before operating on shared resources.
Be sure to release the lock after completing the operation.
Take up the lock as short as possible.
If there are multiple locks, if the order of acquisition is ABC chain buckle, the release order should also be ABC.
The lock that it acquires should be released when a thread error returns.
Let's take a test applet to learn more about mutual exclusion. The mutex mutex semaphore locks not a variable, but blocks a program. If a mutex variable testlock is executed for the first time after pthread_mutex_lock(testlock), if there are other threads executing pthread_mutex_lock(testlock) during the period before unlock(testlock), the thread will block until The previous thread can be executed after it is unlocked. Therefore, synchronization is achieved, and the purpose of protecting the critical section resources is achieved.
#
Include
Pthread_join(test_thread,NULL); pthread_mutex_destroy(&testlock); return 0;}makegcc -D_REENTRANT -lpthread -o test test.c
result:
Main lock Main unlock thread Test()
Second, the condition variable
Here mainly talk about the usage of pthread_cond_wait(), which is explained below.
Conditional variables are a mechanism for synchronizing with global variables shared between threads. They mainly include two actions: one thread waits for "the condition of the condition variable is established" and hangs; the other thread makes "conditional" (given the condition is established) signal). To prevent competition, the use of condition variables is always combined with a mutex. 1. Creating and Unregistering Condition variables, like mutex locks, have both static and dynamic creation methods. Statically, the PTHREAD_COND_INITIALIZER constant is used, as follows:
Pthread_cond_t cond=PTHREAD_COND_INITIALIZER
The pthread_cond_init() function is called dynamically, and the API is defined as follows:
Int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
Although the POSIX standard defines attributes for condition variables, it is not implemented in LinuxThreads, so the cond_attr value is usually NULL and is ignored. To unregister a condition variable, you need to call pthread_cond_destroy(). The condition variable can be unregistered only if no thread is waiting on the condition variable, otherwise EBUSY is returned. Because the condition variables of the Linux implementation do not allocate any resources, the logout action only includes checking if there are waiting threads. The API is defined as follows: int pthread_cond_destroy(pthread_cond_t *cond) 2. Waiting and exciting
Int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
There are two ways to wait for a condition: unconditionally waiting for pthread_cond_wait() and timing waiting for pthread_cond_timedwait(), where the timing wait mode returns ETIMEOUT if the condition is not met before the given time, ending the wait, where abstime is the same as the time() system call The absolute time form of meaning appears, with 0 being 0:00:00 on January 1, 1970, GMT. Regardless of the wait mode, it must be combined with a mutex to prevent multiple threads from requesting the race condition of pthread_cond_wait() (or pthread_cond_timedwait(), the same below). The mutex mutex must be a normal lock (PTHREAD_MUTEX_TIMED_NP) or an adaptive lock (PTHREAD_MUTEX_ADAPTIVE_NP), and must be locked by this thread (pthread_mutex_lock()) before calling pthread_cond_wait(), and the mutex remains locked until the condition waits for the queue. Unlock before the thread hangs into waiting. Before the condition is met and leaves pthread_cond_wait(), the mutex will be relocked to correspond to the locking action before entering pthread_cond_wait(). The pix_cond_wait() is executed to automatically unlock the mutex (as if pthread_unlock_mutex was executed) and wait for the condition variable to fire. At this point the thread hangs and does not take up CPU time until the condition variable is triggered.
Therefore, the whole process can be described as:
(1) pthread_mutex_lock() is locked,
(2) pthread_cond_wait () waits, waiting for the process to be decomposed into: unlock - condition satisfied - lock
(3) pthread_mutex_unlock() is unlocked.
There are two forms of firing conditions. pthread_cond_signal() activates a thread waiting for the condition. When there are multiple waiting threads, one of them is activated in the order of enqueue; and pthread_cond_broadcast() activates all waiting threads. If there is no waiting thread, then nothing will be done.
The following question asked by a child's shoes explains the above description:
When pthread_cond_t calls pthread_cond_wait to enter the wait state, the pthread_mutex_t mutex signal is invalid.
The sample code is as follows:
/ / Multi-threaded synchronization - conditional lock (equivalent to windows events) test
/ / First let pthread_cond_wait enter the wait signal state, in order to call pthread_cond_signal send signal, it is valid.
/ / Can not let pthread_cond_signal execute in front of pthread_cond_wait
#include
#include
#include
Pthread_cond_t g_cond /*=PTHREAD_MUTEX_INITIALIZER*/; //Declare the bar lock and initialize it with a macro
Pthread_mutex_t g_mutex ;
/ / Thread execution function
Void threadFun1(void)
{
Int i;
Pthread_mutex_lock(&g_mutex); //1
Pthread_cond_wait(&g_cond,&g_mutex); //If g_cond has no signal, it will block
For( i = 0;i < 2; i++ ){
Printf("thread threadFun1.");
Sleep(1);
}
Pthread_cond_signal(&g_cond);
Pthread_mutex_unlock(&g_mutex);
}
Int main(void)
{
Pthread_t id1; //thread identifier
Pthread_t id2;
Pthread_cond_init(&g_cond, NULL); // can also be initialized in the program
Pthread_mutex_init(&g_mutex,NULL); //mutually variable initialization
Int i,ret;
Ret = pthread_create(&id1,NULL,(void *)threadFun1, NULL);
If ( ret!=0 ) { //not 0 indicates that thread creation failed
Printf ("Create pthread1 error!");
Exit (1);
}
Sleep(5); //waiting the child thread to start first
Pthread_mutex_lock(&g_mutex); //2
Pthread_cond_signal(&g_cond); // give a start signal, note that the child thread must wait for the wait state to signal, otherwise it will be invalid.
Pthread_mutex_unlock(&g_mutex);
Pthread_join(id1,NULL);
Pthread_cond_destroy(&g_cond); //release
Pthread_mutex_destroy(&g_mutex); //release
Return 0;
}
Please see the red color 1 and 2.
Obviously, 1 locks the mutex variable first, but the code execution to 2 is still the same.
Why is this so????/
Pthread_cond_wait() will lock the lock and continue running... Now let's take a look at a typical application: look at the comments.
Problem explanation: When the program enters pthread_cond_wait and waits, g_mutex will be unlocked. When leaving pthread_cond_wait, g_mutex will be re-locked. So g_mutex in main will be locked. Ha ha. . .
Now let's look at a typical application: just look at the comments.
#include
#include
Cbd Vape Products Oem,D8 Vape Pen Oem,Cbd Disposable Vape Pen Oem,China Cbd Vape Products Oem
Shenzhen MASON VAP Technology Co., Ltd. , https://www.cbdvapefactory.com