The concept of thread synchronization
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.
Examples of thread synchronization
Create two threads, let the two threads share a global variable int number, and then let each thread count 5000 times. See what the number value is printed out at last?
Thread A code snippet:
Thread B snippet:
Code snippet Description:
The purpose of calling usleep in the code is to enable two sub threads to use the CPU in turn, so as to avoid a sub thread completing 5000 times in a time slice. Perform + + operation on number and use the intermediate variable cur to simulate the situation that the CPU runs out of time slices and gives up the CPU as much as possible.
Test results: after many tests, the final results show that the number value may be less than 5000 * 2 = 10000.
Analysis reason:
If child thread A finishes executing cur + + operation and has not assigned the value of cur to number, it loses the execution right of cpu, child thread B gets the execution right of cpu, and child thread B finally executes number=cur, and then loses the execution right of cpu; At this time, sub thread A obtains the execution right of the cpu again and executes the operation number=cur. In this way, the value of number just written back by thread B will be overwritten, resulting in the number value not meeting the expected value.
How to solve this problem:
Linux provides a mutex (also known as mutex). Each thread attempts to lock the resource before operating. The operation can only be performed after locking successfully. The operation is unlocked after the operation is completed.
Resources are still shared and threads compete, but the access to resources will become mutually exclusive through "lock", and then time-related errors will not occur again.
When thread 1 accesses shared resources, it must first judge whether the lock is locked. If it is locked, it will block the waiting; If the lock is unlocked, lock the lock. At this time, you can access the shared resources. After the access is completed, release the lock, so that other threads have a chance to obtain the lock.
It should be noted that only one thread can hold the lock at the same time in the figure. As long as the thread does not complete the operation, the lock will not be released. After using mutex, the two threads changed from parallel operation to serial operation, which reduced the efficiency, but the problem of inconsistent data was solved.
Mutex main correlation function
pthread_mutex_t mutex; Define mutex
pthread_ mutex_ init(&mutex, NULL); Mutex initialization
pthread_ mutex_ lock(&mutex); Lock
pthread_ mutex_ unlock(&mutex); Unlock
pthread_ mutex_ destroy(&mutex); Destroy mutex
#include <stdio.h> #include<iostream> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> #include <time.h> using namespace std; #define NUM 20000 int number = 0; //Define a lock pthread_mutex_t mutex; void *mythread1(void *args) { int i = 0; int n; for (i = 0; i < NUM; i++) { //Lock pthread_mutex_lock(&mutex); n = number; n++; number = n; cout << "[" << n << "]" << endl; //Unlock pthread_mutex_unlock(&mutex); } } void *mythread2(void *args) { int i = 0; int n; for (i = 0; i < NUM; i++) { //Lock pthread_mutex_lock(&mutex); n = number; n++; number = n; cout << "[" << n << "]" << endl; //Unlock pthread_mutex_unlock(&mutex); } } int main() { int ret; pthread_t thread1; pthread_t thread2; //Mutex initialization pthread_mutex_init(&mutex, NULL); ret = pthread_create(&thread1, NULL, mythread1, NULL); if(ret!=0) { cout << "pthread_create error, " << strerror(ret) << endl; return -1; } ret = pthread_create(&thread2, NULL, mythread2, NULL); if(ret!=0) { cout << "pthread_create error, " << strerror(ret) << endl; return -1; } //Wait for the thread to end pthread_join(thread1, NULL); pthread_join(thread2, NULL); //Release mutex pthread_mutex_destroy(&mutex); return 0; }
After running the code several times, the result is still 40000. The successful use of mutex eliminates the problem of thread synchronization.