This article reproduced from: http://blog.csdn.net/ljianhui/article/details/10875883 the previous article, the book connected to one back, in the previous article: Linux multithreading-Using semaphore synchronization thread, We left a question of how to use mutex to thread synchronization, this article will give a detailed explanation of the mutex, and with a mutex to solve the previous article, to use two semaphores to solve only the child thread end the processing and statistics of the input, the main thread can continue to execute the problem. One, what is a mutex mutex is another synchronous access method used in multi-threading, 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 the operation is complete. Second, the use of the mutex function is very similar to the function that uses semaphores, they are defined as follows:
[CPP]View PlainCopyprint?
- #include <pthread.h>
- int pthread_mutex_init (pthread_mutex_t *mutex, < span class= "keyword" >const pthread_mutexattr_t *mutexattr);
- &NBSP;&NBSP;
- int pthread_mutex_lock (Pthread_mutex_t *mutex);
Li class= "alt" >&NBSP;&NBSP;
- int pthread_mutex_unlock (pthread_mutex_t *mutex);
- &NBSP;&NBSP;
- int pthread_ Mutex_destroy (Pthread_mutex_t *mutex);
Their meaning, as their names show, returns 0 on success, returns an error code on failure, and does not set errno. The arguments in the Pthread_mutex_init function mutexattr Specify the property of the mutex, where we do not care about the property of the mutex, so set it to null and use the default property. Similarly, Pthread_mutex_lock and Pthread_mutex_unlock are atomic operations, and if a thread calls Pthread_mutex_lock trying to lock the mutex, and that mutex is locked (occupied) by another thread, The thread's Pthread_mutex_lock call is blocked until the mutex is unlocked by the other thread, and the Pthread_mutex_lock call is returned. Note that using the default property of the mutex, if the program tries to call Pthread_mutex_lock on an already locked mutex, the program will block, and because the thread that owns the mutex is the thread that is now blocked, the mutex will never be unlocked, which means The program will enter the deadlock state. Be careful when you use it, and be sure to unlock the locked mutex again before locking it in the same thread. Iii. using mutex for thread synchronization The following is a simple multithreaded program that demonstrates how to use mutexes for thread synchronization. In the main thread, we create a sub-thread and pass the array msg as an argument to the child thread, then the main thread calls the function Pthread_mutex_lock locks the mutex, waits for input, and after the input completes, calls the function Pthread_mutex_unlock unlocks the mutex. The Pthread_mutex_lock function that locks the mutex in the thread function returns and executes the code in the child thread. After the thread function turns the lowercase letter of the string into uppercase and counts the number of characters entered, it calls Pthread_mutex_unlock to unlock the mutex so that the main thread can continue to obtain the mutex (that is, to return the lock function) and perform the input function again until the main thread calls Pthread again. 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:
[CPP]View PlainCopyprint?
- #include <unistd.h>
- #include <pthread.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- Declaring thread functions and mutexes
- void* Thread_func (void *msg);
- pthread_mutex_t Mutex;
- #define MSG_SIZE 512
- int main ()
- {
- int res =-1;
- pthread_t thread;
- void *thread_result = NULL;
- char Msg[msg_size] = {'} '};
- //Initialize mutex, use default Mutex property
- res = Pthread_mutex_init (&mutex, NULL);
- if (res! = 0)
- {
- Perror ("Pthread_mutex_init failed\n");
- Exit (Exit_failure);
- }
- //Create a sub-thread and pass MSG as a parameter to 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, end at string ' End '
- printf ("Input some test. Enter ' End ' to finish\n ");
- //Lock mutex mutex to ensure that only the thread can access the data in MSG at the same time
- Pthread_mutex_lock (&mutex);
- while (strcmp ("end\n", msg)! = 0)
- {
- if (strncmp ("TEST", MSG, 4) = = 0)
- {
- strcpy (msg, "copy_data\n");
- }
- Else
- {
- Fgets (msg, msg_size, stdin);
- }
- //Unlock mutex mutex so that other threads can access the data in MSG
- Pthread_mutex_unlock (&mutex);
- Sleep (1); //Hibernate for 1 seconds and continue the loop so that other threads have an opportunity to execute
- Pthread_mutex_lock (&mutex);
- }
- Pthread_mutex_unlock (&mutex);
- printf ("\nwaiting for Thread finish...\n");
- //wait for the child thread to end
- res = Pthread_join (thread, &thread_result);
- if (res! = 0)
- {
- Perror ("Pthread_join failed\n");
- Exit (Exit_failure);
- }
- printf ("Thread joined\n");
- //Clean up mutex amount
- Pthread_mutex_destroy (&mutex);
- Exit (exit_success);
- }
- void* Thread_func (void *msg)
- {
- int i = 0;
- char *ptr = msg;
- Sleep (1);
- //Lock mutex mutex to ensure that only the thread can access the data in MSG at the same time
- Pthread_mutex_lock (&mutex);
- while (strcmp ("end\n", msg)! = 0)
- {
- //Turn lowercase letters into 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 mutex mutex so that other threads can access the data in MSG
- Pthread_mutex_unlock (&mutex);
- Sleep (1); //Hibernate for 1 seconds and continue the loop so that other threads have an 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, here first of all in the main function and the thread function Thread_func in the while loop in the function of the sleep (1) statement. A lot of people may think that this sleep (1) is for the child thread to complete its processing and statistics functions, so let the main thread hibernate for 1 seconds to wait for the child thread to finish processing the statistical work. It's true that the sub-threads are doing a very simple job, and in 1 seconds you can actually handle the statistics. But the sleep here (1) is not to achieve this function, the two loops of sleep (1) is to let other threads have the opportunity to be executed, if there is no such statement between the lock and unlock, then the current thread will always be in the loop to obtain the mutex amount, Because other threads do not have the time to execute its code, it is necessary to use such a statement to give other threads a chance to run. If the child thread takes more than 1 seconds to execute, the program will run normally. In this case, in the main thread, when the input data is complete and the mutex is unlocked, does not immediately loop to lock it, at this time the child thread has the opportunity to execute, it will lock the mutex, similarly, when it processing statistics input data, it before entering the next cycle, it also sleeps 1 seconds, Let the main thread have the opportunity to run again. When the main thread is able to execute, it depends on when the child thread unlocks the mutex. Because if the child thread owns (locks) The mutex, the function pthread_mutex_lock in the main thread does not return, leaving the main thread in a blocked state. In other words, the main thread can continue execution and write data to the MSG only after the child thread has finished processing and counting the inputs. See here, you should know that before the use of semaphores, we use a more semaphore is also to achieve this goal. So when we enter test, the program has two inputs, but it still works, which solves the problem of using a semaphore before. The role of semaphores and mutexes are mutually exclusive devices that protect code snippets, and they are very similar. However, in this case, the same function is achieved with the use of semaphores, if the semaphore is used, then two semaphores are required, and only one is needed if the mutex is used. It can be said that the use of mutexes is simpler in this case. But I think the use of mutexes is more likely to make mistakes, and we can see in this example that we need to use the sleep statement to get other threads to execute, but in a program that uses semaphores, it doesn't need to use sleep, which is relatively straightforward. I know it may be my implementation is not good, but for the use of mutex, I think for a long time also thought not to use sleep method.
Linux multithreading-Synchronizing threads with mutexes "Go"