- Linux system programming mutex semaphores, multitask mutex and synchronization
- mutex
- Operation of Mutex
- Create Mutex
- Initialize Mutex
- Mutex Lock Lock (1) Most commonly used
- function
- parameter
- Return value
- Mutex Lock Lock (2) Less commonly used
- function
- parameter
- Return value
- Mutex Lock Unlock
- function
- parameter
- Return value
- Destroy Mutex
- function
- parameter
- Return value
- Examples of using mutexes
- Consequences of not using mutexes
- After using mutex
- Semaphore
- Semaphores are typically used for synchronization and mutual exclusion between processes or threads
- Semaphores for Mutual Exclusion
- Semaphore for synchronization
- >Operation of semaphores
- Initialization of semaphores
- p-operation of semaphore
- v operation of semaphore
- Get the count value of the semaphore
- Destruction of semaphores
- Use of semaphores
- Semaphore for Mutual Exclusion
- The semaphore implements synchronization.
- Popular Keywords
Linux system programming mutex semaphores, multitask mutex and synchronization
In a multitask operating system, multiple tasks running at the same time may need to access/use the same resource. Many tasks depend on each other. One task depends on another task. Synchronization and mutually exclusion are the solutions to both problems.
mutex
A common resource can only be used by one process or thread at a time. Multiple processes or threads cannot use the common resource at the same time. The synchronization and mutually exclusive methods of processes and threads in POSIX standard include semaphore and mutually exclusive lock.
synchronization
Two or more processes or threads coordinate their steps during operation. Running synchronization in a predetermined order is based on mutual exclusion.
mutex
The concept of mutex:
Mutex is a simple locking method to control access to shared resources. Mutex has only two states, lock and unlock. Mutex should be applied for first before accessing the resource. If mutex is in unlock state, mutex will be applied for and immediately locked.
If mutex is locked, the applicant is blocked by default
The unlock operation should be performed by the locker
Operation of Mutex
Create Mutex
Mutex with pthread_ Mutex_ The t data type indicates that the mutex must be initialized before it can be used
Statically Assigned Mutex
pthread_mutex_t mutex= PTHREAD_MUTEX_INITALIZER;
Dynamic allocation of mutex
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);
When all threads that have used this mutex no longer need to use it, it should be called
pthread_mutex_destory destroy mutex
Initialize Mutex
#include int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr)
Functions:
Initialize a mutex
Parameters:
Mutex: mutex address
attr: Mutex property, NULL is the default property
Return value
Successful return 0, failure return non-0
Mutex Lock Lock (1) Most commonly used
#include int pthread_mutex_lock(pthread_mutex_t *mutex);
function
Lock the mutex, and if it is already locked, the caller will block until the mutex is unlocked
parameter
Mutex: Mutex address, which is the specified mutex
Return value
Successful return 0, failure return non-0
Mutex Lock Lock (2) Less commonly used
#include int pthread_mutex_trylock(pthread_mutex_t *mutex);
function
Lock on mutex, if already locked, lock fails, function returns immediately
parameter
Return value
Successful return 0, failure return non-0
Mutex Lock Unlock
#include int pthread_mutex_unlock(pthread_mutex_t * mutex);
function
Unlock the specified mutex
parameter
Return value
Successful return 0, failure return non-0
Destroy Mutex
#include int pthread_mutex_destroy(pthread_mutex_t *mutex);
function
Destroy a specified mutex
parameter
Return value
Successful return 0, failure return non-0
Examples of using mutexes
Consequences of not using mutexes
#include #include #include #include int money = 10000; void *pthread_fun1(void* arg) < int get, yu, shiji; get = 10000; printf("Zhang San is inquiring about the balance. \n"); sleep(1); yu = money; printf("Zhang San is drawing money. \n"); sleep(1); if(get >yu) < shiji = 0; >else < shiji = get; yu = yu - get; money = yu; >printf("Zhang San wants to go %d The money has actually gone %d money ,The balance is %d money\n", get ,shiji, yu); pthread_exit(NULL); > void * pthread_fun2(void* arg) < int get, yu, shiji; get = 10000; printf("Li Si is inquiring about the balance\n"); sleep(1); yu = money; printf("Li Si is drawing money\n"); sleep(1); if(get >yu) < shiji = 0; >else < shiji = get; yu = yu - get; money = yu; >printf(" Li Si wants to take %d Money actually taken %d Money balance is%d money\n", get, shiji, yu); pthread_exit(NULL); > int main() < pthread_t thread1, thread2; if(pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0) < perror("fail to pthread_create"); exit(1); >if(pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0) < perror("fail to pthread_create"); exit(1); >pthread_join(thread1,NULL); pthread_join(thread2,NULL); return 0; >
A total of 10,000 yuan, the main card, and the secondary card, two people together, the result is two people take 10,000 yuan, so reasonable, certainly unreasonable, the bank will not let you do so
After using mutex
#include #include #include #include int money = 10000; ---------Step One---------Mutex Use the first step to create a mutex--- pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; void *pthread_fun1(void* arg) < int get, yu, shiji; get = 10000; ---------Step 3---------Lock operations on shared resources--- pthread_mutex_lock(&mymutex); printf("Zhang San is inquiring about the balance. \n"); sleep(1); yu = money; printf("Zhang San is drawing money. \n"); sleep(1); if(get >yu) < shiji = 0; >else < shiji = get; yu = yu - get; money = yu; >printf("Zhang San wants to go %d The money has actually gone %d money ,The balance is %d money\n", get ,shiji, yu); ---------Step 5---------Unlock mutually exclusive locks after a shared resource operation is completed--- pthread_mutex_unlock(&mymutex); pthread_exit(NULL); > void * pthread_fun2(void* arg) < int get, yu, shiji; get = 10000; ---------Step 4---------Lock operations on shared resources--- pthread_mutex_lock(&mymutex); printf("Li Si is inquiring about the balance\n"); sleep(1); yu = money; printf("Li Si is drawing money\n"); sleep(1); if(get >yu) < shiji = 0; >else < shiji = get; yu = yu - get; money = yu; >printf(" Li Si wants to take %d Money actually taken %d Money balance is%d money\n", get, shiji, yu); ---------Step 6---------Unlock mutually exclusive locks after a shared resource operation is completed--- pthread_mutex_unlock(&mymutex); pthread_exit(NULL); > int main() < ---------Step 2---------Initialize Mutex------- pthread_mutex_init(&mymutex,NULL); pthread_t thread1, thread2; if(pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0) < perror("fail to pthread_create"); exit(1); >if(pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0) < perror("fail to pthread_create"); exit(1); >pthread_join(thread1,NULL); pthread_join(thread2,NULL); ---------Step 7--------Destroy mutex after use of mutex------- pthread_mutex_destroy(&mymutex); return 0; >
Semaphore
Semaphores are widely used for synchronization and mutually exclusion between processes or threads. Semaphores are essentially non-negative integer counters that are used to control access to public resources
Programming can use the result of manipulating the semaphore value to determine whether or not you have access to public resources. When the semaphore value is greater than 0, it can be accessed, otherwise it will be blocked
The P V primitive is to operate a semaphore with a P operation to reduce the SEM by 1, and a V operation to add 1 to the sem. For a P operation, if the SEM value of the semaphore is less than or equal to 0, the P operation will be blocked. If the SEM value of the semaphore is greater than 0, the P operation can be performed to reduce 1.
Semaphores are typically used for synchronization and mutual exclusion between processes or threads
1. For mutually exclusive, several processes (or threads) tend to set only one semaphore
2. When used for synchronous operations, multiple semaphores are often set and different initial values are arranged to achieve the order of execution between them.
Semaphores for Mutual Exclusion
Semaphores are used for mutual exclusion. First, the semaphore is initialized, p-operated, thread 1 executes, then v-operated, second, p-operated, thread 2 executes. To execute v-operated also means that since the semaphore value is 1, it means who executes p-operated first between the two threads. Once a thread executes p-operated first, the semaphore becomes 0. So another thread will block when it sees that the semaphore value is zero, so when a thread finishes executing the V operation, it will + 1 the original semaphore value, then after changing from 0 to 1, the other thread will be able to execute normally, which is the basic nature of semaphores used to mutually exclusive it
Semaphore for synchronization
Two semaphores are set here. (If there are only two threads, one is fine.) First, set the value of semaphore 1 to 1, the value of semaphore 2 to 0, Thread 1 to perform the p operation of SEM 1, Thread 2 to perform the p operation of sem2, since the initial Sem2 value is 0, the position of thread 2 will be blocked, so thread 1 to perform the p operation first, after execution, Thread 1 is running normally. When thread 2’s v operation changes SEM 2’s value from + 1 to 1 after thread 2’s operation, then my thread 2 can execute p operation normally. This is a synchronization problem through semaphores
>Operation of semaphores
Initialization of semaphores
#include int sem_init(sem_t *sem, int pshared, unsigned int value);
function
Create a semaphore and initialize its value
parameter
sem: Address of semaphore
pshared: equal to 0, semaphores are shared between threads; Not equal to 0, semaphores are shared between processes
Value: Initial value of semaphore
Return value
Successfully returned 0, failed returned -1
p-operation of semaphore
#include int sem_wait(sem_t* sem);
function
Reduce the semaphore value by 1. If the semaphore value is less than or equal to 0, this function will cause the caller to block
parameter
sem; Semaphore address
Return value
Successfully returned 0, failed returned -1
This one below is not commonly used, not blocked
#include int sem_trywait(sem_t *sem);
function
Reduce the value of the semaphore by 1. If the value of the semaphore is less than or equal to 0, the operation on the semaphore fails and the function returns immediately
parameter
sem: semaphore address
Return value
Successfully returned 0, failed returned -1
v operation of semaphore
#include int sem_post(sem_t *sem);
function
Increase the semaphore value by 1 and signal wake-up waiting threads
parameter
sem: semaphore address
Return value
Successfully returned 0, failed returned -1
Get the count value of the semaphore
#include int sem_getvalue(sem_t *sem, int *sval);
function
Gets the sem-identified semaphore value, which is saved in sval
parameter
sem: semaphore address
sval: Address to store semaphore values
Return value
Successfully returned 0, failed returned -1
Destruction of semaphores
#include int sem_destory(sem_t *sem);
function
Delete sem-denoted semaphores
parameter
sem: semaphore address
Return value
Successfully returned 0, failed returned -1
Use of semaphores
Semaphore for Mutual Exclusion
No semaphores were added first
#include #include #include #include void printer(char* str) < while(*str) < putchar(*str); //Output a character fflush(stdout);//Refresh Buffer str++; sleep(1); //Output a character every second >> void* thread_fun1(void* arg) < char* str1 = "hello"; printer(str1); >void* thread_fun2(void* arg) < char* str2 = "world"; printer(str2); >int main()
You can see that it’s not the hello world or world hello we want
#include #include #include #include #include //Step 1 Create a semaphore sem_t sem; void printer(char* str) < //Step 3 Perform the p operation //Since semaphores are used for mutual exclusion and the initial semaphore value is set to 1, two threads perform a p-operation //Threads that execute the p operation continue to execute, then blocked waiting for the p operation to execute sem_wait(&sem); while(*str) < putchar(*str); //Output a character fflush(stdout);//Refresh Buffer str++; sleep(1); //Output a character every second >//Step 4 Perform the v operation sem_post(&sem); > void* thread_fun1(void* arg) < char* str1 = "hello"; printer(str1); >void* thread_fun2(void* arg) < char* str2 = "world"; printer(str2); >int main() < //The second step initializes the semaphore sem_init(&sem, 0, 1); pthread_t tid1, tid2; pthread_create(&tid1, NULL, thread_fun1, NULL); pthread_create(&tid2, NULL, thread_fun2, NULL); pthread_join(tid1,NULL); pthread_join(tid2,NULL); printf("\n"); sem_destroy(&sem); return 0; >
Equivalent to printing two files at the same time, cannot first line first file content, second line second file content
The semaphore implements synchronization.
Synchronization is sequential printing on a mutually exclusive basis
#include #include #include #include #include char ch = ‘a’; void* pthread_g(void* arg) < while(1) < ch++; sleep(1); >> void* pthread_p(void* arg) < while(1) < printf("%c", ch); fflush(stdout); >> int main()
What we want is to print a every second and do this, but the results are obviously different
So add semaphores to solve synchronization problems
#include #include #include #include #include char ch = 'a'; //Synchronization using semaphores requires two semaphores if two threads synchronize //The first step is to create two semaphores sem_t sem_g, sem_p; void* pthread_g(void* arg) < while(1) < //In the thread that executes after step 4, perform the p operation on a semaphore whose initial value is set to 0 sem_wait(&sem_g); ch++; sleep(1); sem_post(&sem_p); //Step 6: A semaphore with an initial semaphore value of 1 performs a v-operation after the thread that executes the post-execution finishes executing >> void* pthread_p(void* arg) < while(1) < //In the thread that executes first, the semaphore whose initial semaphore value is set to 1 performs the p operation sem_wait(&sem_p); printf("%c", ch); fflush(stdout); sem_post(&sem_g); //Step 5: When the thread that executes first finishes executing, the semaphore with initial semaphore value of 0 needs to be executed v >> int main() < // The second step initializes the semaphore sem_init(&sem_g, 0 ,0); sem_init(&sem_p, 0 ,1); pthread_t tid1, tid2; pthread_create(&tid1, NULL, pthread_g, NULL); pthread_create(&tid2, NULL, pthread_p, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); printf("\n"); //Step 7 Destroy semaphores after use sem_destroy(&sem_g); sem_destroy(&sem_p); return 0; >
The results are as follows:
We used semaphores to synchronize threads by letting it print, then change, and then print
Added by vurentjie on Fri, 10 Dec 2021 19:10:07 +0200
Popular Keywords
- Java — 6234
- Python — 2579
- Javascript — 2100
- Database — 1608
- Linux — 1477
- Back-end — 1449
- Front-end — 1432
- Spring — 1358
- Algorithm — 1311
- Android — 1124
- MySQL — 1040
- C++ — 1022
- Programming — 966
- network — 827
- data structure — 820
- Attribute — 785
- C — 721
- github — 646
- less — 645
- SQL — 639