Thread synchronization
Concept of synchronization
The so-called synchronization means starting at the same time and coordinating. Different objects have a slightly different understanding of "synchronization". For example, equipment synchronization refers to specifying a common time reference between two equipment; Database synchronization is to keep the contents of two or more databases consistent, or partially consistent as needed; File synchronization refers to keeping files in two or more folders sensitive. wait.
However, the concept of synchronization in programming and communication is slightly different from that in people's impression in life. The word "Tong" shall refer to coordination, assistance and mutual cooperation, with the main purpose of working in a coordinated pace and in a predetermined order;
Thread synchronization
Synchronization is co synchronization, which runs in a predetermined order.
Thread synchronization means that when a thread makes a function call, the call will not return until the result is obtained. At the same time, other threads cannot call this function to ensure data consistency.
Two threads access the same piece of shared resources. If they do not coordinate the order, it is easy to cause data confusion.
Solve the synchronization problem: lock
_ mutex correlation function
#include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); // Constant initialization pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
restrict keyword restricts that the variables corresponding to the memory area of the block can only be modified through the following variables
Mutex mutex lock
The attribute of attr mutex can be ignored and NULL is passed
#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); // Lock int pthread_mutex_trylock(pthread_mutex_t *mutex); // Try locking int pthread_mutex_unlock(pthread_mutex_t *mutex); // Unlock
pthread_mutex_lock blocking wait
If the current lock is not successful, the thread will lock it· If it has been locked, block and wait!
#include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex); // Destroy mutex int pthread_mutex_init(pthread_mutex_t *restrict mutex, // Initialize mutex const pthread_mutexattr_t *restrict attr); // Constant initialization pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Use mutex
Unused semaphores
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #include<pthread.h> int sum = 0; void *thr1(void *arg) { while(1) { printf("hello"); sleep(rand()%3); printf("world\n"); sleep(rand()%3); } } void *thr2(void *arg) { while(1) { printf("HELLO"); sleep(rand()%3); printf("WORLD\n"); sleep(rand()%3); } } int main() { pthread_t tid1,tid2; pthread_create(&tid1,NULL,thr1,NULL); pthread_create(&tid2,NULL,thr2,NULL); pthread_join(tid1,NULL); pthread_join(tid2,NULL); return 0; }
Operation results:
[ dai@localhost 06 thread - 2] $. / 01 not using mutex
HELLOhelloWORLD
HELLOworld
WORLD
helloHELLOWORLD
HELLOworld
WORLD
HELLOhelloWORLD
world
helloworld
^Z
[1] + stopped. / 01 mutex not used
Use mutex
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #include<pthread.h> // Constant initialization pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int sum = 0; void *thr1(void *arg) { while(1) { // Lock pthread_mutex_lock(&mutex); printf("hello"); sleep(rand()%3); printf("world\n"); // Unlock pthread_mutex_unlock(&mutex); sleep(rand()%3); } } void *thr2(void *arg) { while(1) { // Lock pthread_mutex_lock(&mutex); printf("HELLO"); sleep(rand()%3); printf("WORLD\n"); // Unlock pthread_mutex_unlock(&mutex); sleep(rand()%3); } } int main() { pthread_t tid1,tid2; pthread_create(&tid1,NULL,thr1,NULL); pthread_create(&tid2,NULL,thr2,NULL); pthread_join(tid1,NULL); pthread_join(tid2,NULL); return 0; }
Operation results:
[ dai@localhost 06 thread - 2] $. / 02 use mutex
HELLOWORLD
helloworld
HELLOWORLD
helloworld
helloworld
HELLOWORLD
helloworld
^C
To use mutexes
- initialization
- Lock
- Execute code logic – operate on shared data
- Unlock
matters needing attention:
Locking requires minimum granularity and cannot occupy the critical area all the time.
Try locking
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #include<pthread.h> // Definitional lock pthread_mutex_t mutex; // Thread operation void* thr(void *arg) { while(1){ pthread_mutex_lock(&mutex); printf("The child thread is locked successfully\n"); sleep(rand()%5); pthread_mutex_unlock(&mutex); printf("Child thread unlock\n"); sleep(2); } return NULL; } int main() { pthread_mutex_init(&mutex,NULL); // Create thread pthread_t tid; pthread_create(&tid,NULL,thr,NULL); // Lock while(1){ sleep(1); int ret = pthread_mutex_trylock(&mutex); if(ret > 0){ printf("Main thread locking failed ret = %d, %s \n",ret,strerror(ret)); } else { printf("The main thread is locked successfully\n"); sleep(rand()%3); pthread_mutex_unlock(&mutex); printf("Main thread unlock\n"); } sleep(1); } // Recycle thread pthread_join(tid,NULL); return 0; }
Operation results:
[ dai@localhost 06 thread - 2] $. / 03 trying to lock
The child thread is locked successfully
Failed to lock the main thread ret = 16, Device or resource busy
Child thread unlock
The main thread is locked successfully
Main thread unlock
The child thread is locked successfully
Failed to lock the main thread ret = 16, Device or resource busy
Child thread unlock
The main thread is locked successfully
Main thread unlock
The child thread is locked successfully
Failed to lock the main thread ret = 16, Device or resource busy
Child thread unlock
^C
Deadlock condition
- Lock and lock, lock yourself once, and then lock again after success.
- The sequence of applying for cross lock shall be consistent. If one lock is applied and the other is not applied, release the other lock.
be careful
mutex is the recommended lock