1. Thread synchronization and mutual exclusion
Critical Section: A section of code that accesses a shared resource
Critical resources: shared resources that are read and written in the critical area, that is, resources that can only be accessed by one process at the same time
If there is communication between threads, a synchronous mutual exclusion mechanism needs to be introduced to avoid race conditions and ensure that only one thread handles critical resources at any time
2. Mutex lock
2.1 Working principle
For threads that want to access critical resources, before accessing, apply for a lock operation. If the lock is successful, they will enter the critical section and access the resources in the critical section until they exit the critical section and unlock the mutex. If the locking fails, the thread enters the dormant waiting stage, waiting for the mutex to be opened.
2.2 Create a mutex
Function: pthread_mutex_init
Function: Create and initialize a mutex
Function prototype:
#include <pthread.h>
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER; //创建方式一
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); //创建方式二
parameter:
pthread_mutex_t *mutex: storage application and initialized mutex
pthread_mutexattr_t *mutexattr: mutex attribute, which can define whether the mutex is used for a process or a thread. You can use the pthread_mutexattr_init function to modify the mutex attribute, generally fill in NULL, which means it is used for threads
return value:
always returns 0;
2.3 Locking
Function: pthread_mutex_lock
Function: lock, if other threads occupy the mutex, this function will block
Function prototype:
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
parameter:
pthread_mutex_t *mutex: Specifies the mutex to be locked
return value:
success, return 0
on failure, return non-zero
2.4 Unlock
Function: pthread_mutex_unlock
Function: Unlock the mutex
Function prototype:
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
parameter:
pthread_mutex_t *mutex: Specifies the mutex to unlock
return value:
success, return 0
on failure, return non-zero
2.5 Destroy lock
Function: pthread_mutex_dsetroy
Function: Destroy the mutex
Function prototype:
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
parameter:
pthread_mutex_t *mutex: Specifies the mutex to be destroyed
return value:
success, return 0
on failure, return non-zero
2.6 Deadlock
The reason for the deadlock: the thread that owns the resource has not unlocked the mutex, and there are often the following situations:
- The thread holding the mutex exited abnormally without releasing the lock resource
- The same thread locks a mutex repeatedly
- Mutex cross nesting
Sample code (creating two threads, one for printing and one for inversion)
#include <stdio.h>
#include <pthread.h>
#include <string.h>
//临界资源
char buf[] = "AAAA____BBBB";
//互斥锁变量 方式二
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* callback1(void* arg)
{
while(1)
{
/******临界区************/
//上锁
pthread_mutex_lock(&mutex);
printf("%s\n", buf);
//解锁
pthread_mutex_unlock(&mutex);
/******临界区************/
}
pthread_exit(NULL);
}
void* callback2(void* arg)
{
char temp = 0;
while(1)
{
/******临界区************/
//上锁
pthread_mutex_lock(&mutex);
for(int i=0; i<strlen(buf)/2; i++)
{
temp = buf[i];
buf[i] = buf[strlen(buf)-1-i];
buf[strlen(buf)-1-i] = temp;
}
//解锁
pthread_mutex_unlock(&mutex);
/******临界区************/
}
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
/*
//创建互斥锁:方式一
if(pthread_mutex_init(&mutex, NULL) != 0)
{
fprintf(stderr, "pthread_mutex_init failed __%d__\n", __LINE__);
return -1;
}
*/
pthread_t tid1, tid2;
//创建线程:打印
if(pthread_create(&tid1, NULL, callback1, NULL) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
pthread_detach(tid1);
//创建线程:倒置
if(pthread_create(&tid2, NULL, callback2, NULL) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
pthread_join(tid2, NULL);
//销毁互斥锁
pthread_mutex_destroy(&mutex);
return 0;
}