Use mutexes to control Linux thread synchronization

  
 

What is a mutex?

A mutex is a method for synchronous access in multithreading, which allows a program to lock an object or a piece of code so that there can only be one at a time. A thread accesses it. In order to control access to key objects or code, you must lock a mutex before entering this code and then unlock it after completing the operation. The essence is the same as the semaphore, it is P/V operation.

Missing related API

For the learning of mutex, you can't do without the learning of various APIs. Before you start coding to achieve a small DEMO, let's take a look at these. API function. /*** Initializes a mutex* @param mutex* The mutex that is finally initialized * @param mutexattr* The property of the mutex * @return returns 0 on success; otherwise returns a non-zero error code, but does not set Errno error value */int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

/*** Mutex for locking operation * @param mutex* Mutex for pthread_mutex_init* @ Return returns 0 if successful; otherwise returns non-zero error code, but does not set errno error value */int pthread_mutex_lock(pthread_mutex_t *mutex);

/*** Mutex unlock operation * @param Mutex* Mutex* obtained by pthread_mutex_init * @return returns 0 on success; otherwise returns non-zero error code, but does not set errno error value */int pthread_mutex_unlock(pthread_mutex_t *mutex);

/* ** Non-blocking version of the pthread_mutex_lock function. * If the mutex specified by the mutex parameter is already locked, * calling the pthread_mutex_trylock function does not block the current thread, but immediately returns a value describing the condition of the mutex. * @param mutex Mutex obtained by pthread_mutex_init * @return returns 0 on success; otherwise returns a non-zero error code, but does not set the error value of errno */int pthread_mutex_trylock(pthread_mutex_t *mutex);

/*** Destroy the created mutex* @param mutex* The mutex obtained by pthread_mutex_init* @return returns 0 on success; otherwise it returns a non-zero error code, but does not set the errno error value */int pthread_mutex_destroy( Pthread_mutex_t *mutex);

A small instance

Well, the introduction of API functions is always so dry, to point out the code to see how to use the mutex. Next I want to code to achieve the following tasks: • the main thread can continuously input letters, when the end is entered, the program is terminated; • the child thread converts the letters input by the main thread into uppercase;

the main thread can The standard input is constantly input, and the child thread can continuously convert. No, directly on the code, the code is a little longer, please read it carefully. #include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <semaphore.h>

void *threadFunc(void *arg);pthread_mutex_t work_mutex;sem_t sem;

#define WORK_SIZE 1024char work_area[WORK_SIZE];

int main(){int res;pthread_t thread1 ;void *threadRes;

res = pthread_mutex_init(&work_mutex, NULL); //Initialize the mutex if (res != 0){perror("Mutex initialization failed.");exit( EXIT_FAILURE);}

res = sem_init(&sem, 0, 0);if (res != 0){perror("Semaphore create failed.");exit(EXIT_FAILURE);}< Br>

res = pthread_create(&thread1, NULL, threadFunc, NULL);if (res != 0){perror("Thread create failed.");exit(EXIT_FAILURE);}

printf("Input some text. Enter 'end' to finish.\ ");pthread_mutex_lock(&work_mutex);while (strncmp(work_area, "end", 3) != 0){fgets(work_area , WORK_SIZE, stdin); pthread_mutex_unlock(&work_mutex);sem_wait(&a Mp;sem); //Tell thread 1, my data is finished, it's your turn to process it, tell me after processing

pthread_mutex_lock(&work_mutex);}pthread_mutex_unlock(&work_mutex);< Br>

printf("\ Waiting for thread to finish...\ ");res = pthread_join(thread1, &threadRes);if (res != 0){perror("Thread join failed. ");exit(EXIT_FAILURE);}

printf("Thread joined.\ ");pthread_mutex_destroy(&work_mutex);sem_destroy(&sem);exit(EXIT_SUCCESS);}

void *threadFunc(void *arg){pthread_mutex_lock(&work_mutex);while (strncmp(work_area, "end", 3) != 0){if (work_area[0] != '\\0' ){for (int i = 0; work_area[i] != '\\0'; ++i){if (work_area[i] >= 'a' && work_area[i] <= 'z '){work_area[i] -= 'a' - 'A';}}

printf("After converted: %s\ ", work_area);sem_post(&sem); //Tell the main thread, I finished processing, it is your turn to read the data memset (work_area, 0, sizeof(work_area));}pthread_mutex_unlock(&work_mutex);sleep(1) ;pthread_mutex_lock(&work_mutex);}

pthread_mutex_unlock(&work_mutex);sem_post(&sem);pthread_exit(NULL);}

The task is complete, not bad. However, it is very difficult to guarantee synchronization in multi-threaded development. Don't look at the above code to complete the task is very simple, but a lot of pits, that is, now, I can not guarantee that the above code is 100% without pits, just waiting for you to pick.

Why is multi-thread synchronization so difficult? Intuitively, the human brain is single-threaded. If you want to go to multi-threaded and think of many things, you will be confused. Just like, let your left hand draw a circle, the right hand draw a square, can you draw a perfect one? The reason is very simple, think more, write more, fill in more pits. guys.

Copyright © Windows knowledge All Rights Reserved