Linux Multithreading uses mutexes to synchronize threads _linux

Source: Internet
Author: User

This article will give a detailed explanation of the mutex, and use a mutex solution in the previous article, two semaphores to solve only after the child thread finished processing and statistics of the input, the main thread can continue to execute the problem.

One, what is mutually exclusive quantity

A mutex is another method for synchronizing access in multiple threads, which allows a program to lock an object so that only one thread can access it at a time. To control access to critical code, you must lock a mutex before entering the code, and then unlock it after you complete the operation.

The use of the function of mutual exclusion

Their definitions are very similar to the functions that use semaphores, and they are defined as follows:

#include <pthread.h> 
int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); 
 
int Pthread_mutex_lock (pthread_mutex_t *mutex); 
 
int Pthread_mutex_unlock (pthread_mutex_t *mutex); 
 

Their meaning, as their name shows, returns 0 when they succeed, and returns an error code when they fail, and they do not set errno.

The parameters in the Pthread_mutex_init function mutexattr Specify the properties of the mutex, where we do not care about the properties of the mutex, so set it to null and use the default property. Similarly, both Pthread_mutex_lock and Pthread_mutex_unlock are atomic operations, and if one thread calls Pthread_mutex_lock attempting to lock the mutex, which is locked (occupied) by another thread, The Pthread_mutex_lock call of the thread blocks until the mutex is unlocked by another thread before the thread can get the mutex, and the Pthread_mutex_lock call returns.

Note that using the default property of a mutex, if the program tries to call Pthread_mutex_lock on a mutex that has been locked, the program blocks, and because the thread that owns the mutex is the thread that is now blocked, the mutex will never be unlocked, that is to say, The program will enter the deadlock state. Be careful when using, and be sure to unlock the mutex again before locking it in the same thread.

Third, the use of mutex for thread synchronization

The following is a simple multithreaded program that demonstrates how to use mutexes to synchronize threads. In the main thread, we create the child threads and pass the array msg as a parameter to the child thread, and then the main thread calls the function Pthread_mutex_lock the mutex, waits for input, after the input completes, calls the function Pthread_mutex_unlock to unlock the mutex, This causes the Pthread_mutex_lock function in the thread function to lock the mutex to return and execute the code in the child thread. After the thread function capitalizes the lowercase letter of the string and counts the number of characters entered, it calls the Pthread_mutex_unlock to unlock the mutex so that the main thread can continue to acquire the mutex (that is, to return the lock function) and perform the input function again until the main thread calls the Pthread The _mutex_unlock unlocks it so that it repeats until the end is entered.

The source file is LOCKTHREAD.C and the source code is as follows:

, #include <unistd.h> #include <pthread.h> #include <stdlib.h> #include <stdio.h> #include 
;string.h>//Declaration of thread functions and mutexes void* thread_func (void *msg); 
 
 
pthread_mutex_t Mutex; 
  #define MSG_SIZE int main () {int res =-1; 
  pthread_t thread; 
  void *thread_result = NULL; 
  Char Msg[msg_size] = {' I '}; 
  Initializes the mutex, using the default mutex attribute res = Pthread_mutex_init (&mutex, NULL); 
    if (res!= 0) {perror ("Pthread_mutex_init failed\n"); 
  Exit (Exit_failure); 
  //Create a child thread and pass MSG as a parameter of the thread function to Thread_func res = pthread_create (&thread, NULL, Thread_func, msg); 
    if (res!= 0) {perror ("pthread_create failed\n"); 
  Exit (Exit_failure); }//input string, ending printf with string ' End ' (' input some test. 
  Enter ' End ' to finish\n '); 
  Lock the mutex to ensure that only the thread can access the data Pthread_mutex_lock (&mutex) in MSG at the same time; 
    while (strcmp ("end\n", msg)!= 0) {if (strncmp ("TEST", MSG, 4) = 0) {strcpy (msg, "copy_data\n"); } ElSE {fgets (msg, msg_size, stdin); 
    //Unlock the mutex mutex so that other threads can access the data Pthread_mutex_unlock (&mutex) in MSG; 
  Sleep (1),//hibernate 1 seconds and then continue to cycle, so that other threads have the opportunity to execute Pthread_mutex_lock (&mutex); 
  } pthread_mutex_unlock (&mutex); 
  printf ("\nwaiting for Thread finish...\n"); 
  Wait child thread End res = pthread_join (thread, &thread_result); 
    if (res!= 0) {perror ("Pthread_join failed\n"); 
  Exit (Exit_failure); 
  printf ("Thread joined\n"); 
  Clean Mutex Pthread_mutex_destroy (&mutex); 
Exit (exit_success); 
  } void* Thread_func (void *msg) {int i = 0; 
  char *ptr = msg; 
  Sleep (1); 
  Lock the mutex to ensure that only the thread can access the data Pthread_mutex_lock (&mutex) in MSG at the same time; while (strcmp ("end\n", msg)!= 0) {//Turn lowercase letters to uppercase for (i = 0; ptr[i]!= '; ++i ') {if (ptr[i) >= 
      ' A ' && ptr[i] <= ' z ') {ptr[i] = ' A '-' a '; 
    } printf ("You input%d characters\n", i-1); printf ("To uppercase:%s\n",PTR); 
    Unlock the mutex mutex so that other threads can access the data Pthread_mutex_unlock (&mutex) in MSG; 
  Sleep (1),//hibernate 1 seconds and then continue to cycle, so that other threads have the opportunity to execute Pthread_mutex_lock (&mutex); 
  } pthread_mutex_unlock (&mutex); 
Exit thread Pthread_exit (NULL); 
 }

The results of the operation are as follows:

Program Analysis:

The workflow of this program has been made very clear, and here is the function of the sleep (1) statement in the while loop in the main function and in the thread function Thread_func. Many people may think that this sleep (1) is for the child thread to complete its processing and statistical functions, so let the main thread hibernate for 1 seconds to wait for the completion of the child thread processing statistics. It is true that the work done by the child threads is very simple, and in 1 seconds it is possible to process the statistics. But the sleep (1) Here is not designed to achieve this function, the sleep (1) in both loops is designed to give other threads a chance to be executed, and if there is no such statement between the lock and the lock at one time, the current thread will always get the mutex in the loop. Because other threads do not have the time to execute their code, it is necessary to use such a statement to give the other threads a chance to run. If the child thread executes longer than 1 seconds, the program will run correctly.

In this case, in the main thread, when the input data is complete and the mutex is unlocked, instead of looping it immediately, the child thread has an opportunity to execute it, locking the mutex, and, similarly, when it processes the data entered, it sleeps for 1 seconds before entering the next cycle, Let the main thread have the opportunity to run again. When the main thread can be executed, it depends on when the child thread unlocks the mutex. Because if the child thread has (locked) mutexes, the function pthread_mutex_lock in the main thread will not return, causing the main thread to be blocked.

In other words, it is only after the child thread has finished processing and counting the input that the main thread can continue to write data to MSG. See here, you should know that before using the semaphore, we use one more signal to achieve this goal. So when we enter test, the program has two inputs, but it still works, and it solves the problem of using a semaphore before.

The role of semaphores and mutexes is to protect the mutex devices of the code snippets, and they are very similar. In this case, however, the same functionality is achieved compared to the use of semaphores, and if the semaphore is used, two semaphores are required, and only one is required to use the mutex. It can be said that in this case, the use of mutexes is simpler. But I think it's easier to make mistakes using mutexes, and we can see in this example that we need to use the sleep statement to give other threads an opportunity to execute, but in a program that uses semaphores, it doesn't need to use sleep, which is relatively intuitive. I know it may be my implementation is not good, but for the use of mutexes, I think for a long time not to use the method of sleep.

Thank you for reading, I hope to help you, thank you for your support for this site!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.