This article can be reproduced at will, but the author and source must be indicated.
[Original] Teach you how to design multiple threads in Linux (3)
-- Multi-thread programming in Linux
Original Author: frozen_socker (popsicle)
E_mail: dlskyfly@163.com
Thread mutex
A mutex operation means that only one thread can execute this code when modifying a code segment or variable. Other threads cannot simultaneously enter this Code or modify this variable. This code or variable is called a critical resource.
For example, there are two threads A and B. The critical resource is X. First, thread a enters and sets X to the locking status. During this period before a opens the lock, if it happens that thread B also wants to obtain X, but it finds that X is locked, it indicates that other threads are executing mutex, so thread B will block itself... Thread a finishes processing. Before exiting, it unlocks X and wakes up other threads. So thread B starts to lock X. In this way, two different threads are operated alternately.
Remember: A mutex can never belong to two threads at the same time. Or in the locked state; or idle, does not belong to any thread.
The Code is as follows:
// Example_3.c
# Include <stdio. h>
# Include <pthread. h>
Void * pthread_func_test (void * Arg );
Pthread_mutex_t mu;
Int main ()
...{
Int I;
Pthread_t pt;
Pthread_mutex_init (& Mu, null); // declare the default attribute of Mu. This row can be left empty.
Pthread_create (& PT, null, pthread_func_test, null );
For (I = 0; I <3; I ++)
...{
Pthread_mutex_lock (& mu );
Printf ("main thread ID: % lu", pthread_self (); // function of pthread_self: Obtain the ID of the current thread
Pthread_mutex_unlock (& mu );
Sleep (1 );
}
}
Void * pthread_func_test (void * Arg)
...{
Int J;
For (j = 0; j <3; j ++)
...{
Pthread_mutex_lock (& mu );
Printf ("New thread ID: % lu", pthread_self ());
Pthread_mutex_unlock (& mu );
Sleep (1 );
}
}
Terminal output result:
The main thread ID is: 3086493376
New thread ID: 3086490512
The main thread ID is: 3086493376
New thread ID: 3086490512
The main thread ID is: 3086493376
New thread ID: 3086490512
Note: The running results on your machine may be different from those shown here.
The pthread_mutex_lock statement begins to lock with a mutex lock. Subsequent code is locked until pthread_mutex_unlock is called, that is, only one thread can call and execute the lock at a time. When another thread executes the lock at pthread_mutex_lock, if the lock is used by other threads at this time, the thread is blocked, that is, the program will wait for other threads to release the mutex lock.
The above example involves several functions: pthread_mutex_init/pthread_mutex_lock/pthread_mutex_unlock/pthread_mutex_destroy/pthread_self
Function prototype:
Int pthread_mutex_init (pthread_mutex_t * restrict mutex,
Const pthread_mutexattr_t * restrict ATTR );
Function functions:
Initialize the mutex variable. The attributes of the variable are specified by ATTR. If ATTR is set to null, the default attribute is used. This method is equivalent to the pthread_mutex_t mutex = pthread_mutex_initializer method.
Function prototype:
Int pthread_mutex_lock (pthread_mutex_t * mutex );
Function functions:
Used to lock mutex variables. If the mutex parameter has been locked, the calling thread will be blocked until other threads unlock the mutex.
Function prototype:
Int pthread_mutex_unlock (pthread_mutex_t * mutex );
Function functions:
If the current thread has the mutex specified by the mutex parameter, the function call will unlock the mutex.
Function prototype:
Int pthread_mutex_destroy (pthread_mutex_t * mutex );
Function functions:
Used to release resources occupied by mutex.
Function prototype:
Pthread_t pthread_self (void );
Function functions:Obtain the thread ID. As we have mentioned earlier, the pthread_t type is unsigned long int, so % lu is used for printing. Otherwise, a strange result is generated.
However, the above Code is not perfect. If the number of loops is modified long enough, the printed result may not be the alternate print we want to see, as shown below:
The main thread ID is: 3086493376
New thread ID: 3086490512
The main thread ID is: 3086493376
New thread ID: 3086490512
New thread ID: 3086490512
The main thread ID is: 3086493376
Why? Because Linux is a time-sharing operating system and uses the time slice rotation method, the main thread and the new thread may obtain non-sequential time slice due to interference from other factors. If you want to strictly achieve the "alternate" mode, you can slightly apply the subtotal, that is, add a flag.
The complete procedure is as follows:
// Example_4.c
# Include <stdio. h>
# Include <pthread. h>
Void * pthread_func_test (void * Arg );
Pthread_mutex_t mu;
Int flag = 0;
Int main ()
...{
Int I;
Pthread_t pt;
Pthread_mutex_init (& Mu, null );
Pthread_create (& PT, null, pthread_func_test, null );
For (I = 0; I <3; I ++)
...{
Pthread_mutex_lock (& mu );
If (flag = 0)
Printf ("main thread ID: % lu", pthread_self ());
Flag = 1;
Pthread_mutex_unlock (& mu );
Sleep (1 );
}
Pthread_join (PT, null );
Pthread_mutex_destroy (& mu );
}
Void * pthread_func_test (void * Arg)
...{
Int J;
For (j = 0; j <3; j ++)
...{
Pthread_mutex_lock (& mu );
If (flag = 1)
Printf ("New thread ID: % lu", pthread_self ());
Flag = 0;
Pthread_mutex_unlock (& mu );
Sleep (1 );
}
}
A deadlock may occur when mutex lock is used: two threads attempt to occupy two resources at the same time and lock the corresponding mutex lock in different order, for example, both threads need to lock mutex lock 1 and mutex lock 2. Thread a First locks mutex lock 1, thread B First locks mutex lock 2, and a deadlock occurs. In this case, we can use the pthread_mutex_trylock function, which attempts to lock a mutex but does not block it.
Function prototype:
Int pthread_mutex_trylock (pthread_mutex_t * mutex );
The pthread_mutex_trylock () function is used to lock the mutex specified by the mutex parameter. If the mutex parameter has been locked, the call will not block waiting for the mutex to unlock, but will return an error code. By judging the returned code, the programmer can handle the deadlock accordingly. Therefore, pay special attention to this in programming multiple mutex.
After the above explanation, we have learned how to operate mutex variables on multithreading in Linux. In the next section, we will explain some knowledge about thread synchronization.