Above, we briefly talked about the application of mutex in multi-threaded synchronization. In this paper, we briefly talked about the application of semaphores in multi-threaded synchronization. First of all, we will briefly talk about the basic concepts and operations of semaphore synchronization between multi-threads, and then write a small example to test it.
Basic concepts and operations of semaphores
The semaphore is essentially a non-negative integer counter, which is used to control access to public resources. Here is a brief review of the operation principle of the PV atom. PV atomic operation is the operation of integer counter sem. One P operation subtracts one SEM and one V operation adds one sem. Processes (or threads) determine whether they have access to public resources based on semaphore values. When the semaphore SEM is greater than or equal to zero, the process (or thread) has access to public resources; conversely, when the semaphore SEM is less than zero, the process (or thread) will block until the semaphore SEM The value is greater than or equal to zero.
Linux implements the anonymous semaphore of POSIX, which is mainly used for mutual exclusion and synchronization between threads. Here are some common functions.
a. Signal initialization function
sem: Identification of the semaphore to be initializedint sem_init(sem_t *sem,int pshared,unsigned int value)
pshared: Decides that semaphores can be shared between several processes if used only in this process, set to 0
Value: semaphore initialization value
Return value: 0 success, other errors
b. Common functions of other semaphores
sem: Identification of semaphores to be operated onint sem_wait(sem_t *sem) // Wait for a semaphore to continue until there is a semaphore int sem_trywait(sem_t *sem) // Wait for a semaphore and return immediately, whether or not int sem_post(sem_t *sem) // Sending semaphore int sem_getvalue(sem_t *sem) // Values used to obtain semaphores int sem_destroy(sem_t *sem) // Destroy a semaphore
Return value: 0 success, other errors
II. Testing
Write a small test example to realize the function: Write three sub-threads, according to the parameters of the main thread to determine how many of the three sub-threads can run at the same time, the complete code is as follows:
Compiling this routine, compiling and linking to add - lpthread, run in three cases:#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <semaphore.h> /* Define a global variable for a semaphore */ static sem_t sem; /* * Thread body of sub-thread a */ static void *start_routine_a (void *arg) { int loop_cnt = (int)arg; int i; sem_wait(&sem); // Waiting semaphore printf("thread A : start!\n"); for(i = 0; i < 5; i++) { printf("TECH-PRO thread A : %d\n", i); sleep(1); } printf("thread A : stop!\n"); sem_post(&sem); // Sending semaphore pthread_exit(NULL); /* Thread Execution Completed */ } /* * Thread body of sub-thread b */ static void *start_routine_b (void *arg) { int loop_cnt = (int)arg; int i; sem_wait(&sem); // Waiting semaphore printf("thread B : start!\n"); for(i = 0; i < 5; i++) { printf("TECH-PRO thread B : %d\n", i); sleep(1); } printf("thread B : stop!\n"); sem_post(&sem); // Sending semaphore pthread_exit(NULL); /* Thread Execution Completed */ } /* * Thread body of subthread c */ static void *start_routine_c (void *arg) { int loop_cnt = (int)arg; int i; sem_wait(&sem); // Waiting semaphore printf("thread C : start!\n"); for(i = 0; i < 5; i++) { printf("TECH-PRO thread C : %d\n", i); sleep(1); } printf("thread C : stop!\n"); sem_post(&sem); // Sending semaphore pthread_exit(NULL); /* Thread Execution Completed */ } /* * Define three sub-threads and decide to run several threads in three threads at the same time based on the value passed in * usage : pthread <1|2|3> */ int main(int argc, char *argv[]) { int ret; int value; pthread_t pthread_a, pthread_b, pthread_c; if(2 != argc) { printf("usage : %s <1|2|3>\n", argv[0]); return -1; } /* Get this value from the incoming parameters */ value = strtoul(argv[1], NULL, 0); if((value < 1) || (value > 3)) { printf("the value is out of boundary!\n"); return -1; } /* Initialization semaphore */ ret = sem_init(&sem, 0, value); if(0 != ret) { printf("sem_init error!\n"); return -1; } /* start */ printf("main : start!\n"); /* Create two sub-threads */ ret = pthread_create(&pthread_a, NULL, start_routine_a, (void *)5); if(0 != ret) { printf("pthread_create for a is failed!\n"); return -1; } ret = pthread_create(&pthread_b, NULL, start_routine_b, (void *)5); if(0 != ret) { printf("pthread_create for b is failed!\n"); return -1; } ret = pthread_create(&pthread_c, NULL, start_routine_c, (void *)5); if(0 != ret) { printf("pthread_create for c is failed!\n"); return -1; } /* Waiting for the process to end */ pthread_join(pthread_a, NULL); pthread_join(pthread_b, NULL); pthread_join(pthread_c, NULL); /* End */ printf("main : stop!\n"); sem_destroy(&sem); // Destruction semaphore return 0; }
When there is only one thread running at the same time:
When two threads can run simultaneously:
When there are three threads running at the same time:
As can be seen from the above results, using signal quantities can determine how many threads can access shared resources and space at the same time.