Using semaphores to control Linux thread synchronization

  

Thread synchronization In real life, some things must be executed in order, only after I have finished, you can continue on my labor results; can't I have not finished yet You are starting to work. This is the most straightforward explanation of thread synchronization.

The same is true when programming. Thread synchronization, what is the synchronization? It synchronizes access to shared resources (memory regions, public variables, etc.) or critical regions. Sometimes, these shared resources and critical areas can only tolerate a thread to operate on it (read or write, read operations are generally not controlled, mainly write operations), at this time, we must have to these shared resources or critical The regions are synchronized, so how do you synchronize them with threads?

The following two methods are mainly provided in Linux:

Synchronization with semaphores Synchronization with mutex No matter what method is used, it is for thread synchronization, and this article A detailed summary of thread synchronization for semaphores.

What is the semaphore first to figure out the concept of semaphores. A semaphore is a special type of variable that can be increased or decreased, but access to it is guaranteed to be atomic, even in a multithreaded program. That is, if two or more threads in a program attempt to change the value of a semaphore, the system will ensure that all operations will be performed in sequence. If you switch to a normal variable, conflicting operations from different threads in the same program will result in an indeterminate operation.

In your work, you will encounter two kinds of semaphores: binary semaphores and counting semaphores. The binary semaphore has only two values, 0 and 1, while the counting semaphore has a larger range of values. If a shared resource can only be accessed by one thread, the binary semaphore is the best idea; if there are multiple threads that need to access the shared resource, it is a good idea to use the count semaphore.

The semaphore-related API has provided some related API interfaces in Linux to implement semaphores. First, mix them with these interfaces, and then use a small example to familiarize yourself with how to use these interfaces.

/*** Create semaphores * @param setm_t* sem Semaphore object, complete initialization of the object * @param int pshared The type of semaphore; if its value is 0, it means this semaphore Is the local semaphore of the current process; otherwise, this semaphore can be shared between multiple processes * @param unsigned int value The initial value of the semaphore * @return int returns 0 on success; -1*/int on failure Sem_init(sem_t *sem, int pshared, unsigned int value);/*** Decrease the value of the semaphore by atomic operation by 1* @param sem_t* The semaphore object obtained by calling sem_init* @return int returns 0 on success ;Failed to return -1*/int sem_wait(sem_t *sem);/*** Add the value of the semaphore by atomic operation by 1* @param sem_t* The semaphore object obtained by calling sem_init* @return int Returns 0; returns -1*/int sem_post(sem_t *sem) on failure; /*** Gets the semaphore count* @param sem_t* sem Semaphore object obtained by calling sem_init* @param int& value Actually returned The value of the semaphore * @return int returns 0 on success; -1*/int on failure Sem_getvalue(sem_t *sem, int &value);/*** Clean up all resources owned by this semaphore; if the semaphore attempting to clean is waiting by some threads, it will receive an error * @param sem_t* Call sem_init to get The semaphore object * @return int returns 0 on success; -1*/int sem_destroy(sem_t *sem) on failure; sem_wait will decrement the value of the semaphore, but it will wait until the value of the semaphore is greater than or equal to At 1 o'clock, the operation of decrementing 1 is started. So, if sem_wait is called on a semaphore with a value of 2, the thread will continue to execute; if a sem_wait operation is performed on a semaphore of 0, the function will wait until another thread increases the value of the semaphore so that it does not It is 0 again.

A small example of API functions for semaphore operations has been introduced, and now use a small program to use these functions, through the actual coding, you can better understand how to use these functions.

The next code is to perform such a function:

The main thread reads the input from the standard input terminal; the child thread 1 converts the input from the main thread into uppercase. Come on, we will implement the code according to the above functions. The function is simple, I am prepared to achieve this:

In the main thread initialization semaphore is 0; When the main thread input is completed, call sem_post to increase the value of the semaphore; in sub-thread 1, call sem_wait, wait until the semaphore A value of 1 reduces the value of the semaphore and then executes the code in the thread. Ok, coding it.

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <pthread.h>#include <semaphore.h>void *threadFunc( Void *arg);sem_t sem;#define WORK_SIZE 1024char work_area[WORK_SIZE]; //Shared resources accessed by both the main thread and the child thread int main(){int res;pthread_t upperThread;void *threadRes;res = sem_init(&sem , 0, 0); //The semaphore is initialized to 0

if (res != 0){perror("Semaphore initialization failed.");exit(EXIT_FAILURE);}

res = pthread_create(&upperThread, NULL, threadFunc, NULL);if (res != 0){perror("Thread creation failed.");exit(EXIT_FAILURE);}printf("Please input convert text , then enter 'end' to finish.\ ");while (strncmp("end", work_area, 3) != 0){fgets(work_area, WORK_SIZE, stdin);sem_post(&sem); //Input complete, increase the value of the semaphore int semValue = 0; res = sem_getvalue(&sem, &semValue); //get the current value of the semaphore printf("Semaphore count: %d\ ", semValue); }

printf("\ Waiting for thread to finish...\ ");res = pthread_join(upperThread, &threadRes);if (res != 0){perror("Thread join failed.") ;exit(EXIT_FAILURE);}printf("Thread joined.\ ");sem_destroy(&sem);exit(EXIT_SUCCESS);}void *threadFunc(void *arg){sem_wait(&sem); //Reduce the value of the semaphore int semValue = 0; sem_getvalue(&sem, &semValue);printf("Semaphore count: %d\ ", semValue);

while (strncmp("end" ;, work_area, 3) != 0){for (int i = 0; work_area[i] != '\\0'; ++i){if (work_area[i] >= 'a' && Work_area[i] <= 'z'){work_area[i] = work_area[i] - 32;}}

printf("After convtered: %s\ ", work_area);sem_wait( &sem); //Block again, waiting for input}pthread_exit(NULL);}

Copyright © Windows knowledge All Rights Reserved