Le quoi et le pourquoi du mutex récursif ne devraient pas être une chose aussi compliquée décrite dans la réponse acceptée.
Je voudrais noter ma compréhension après quelques recherches sur le net.
Tout d'abord, vous devez comprendre que lorsque vous parlez de mutex , les concepts multi-threads sont également impliqués. (le mutex est utilisé pour la synchronisation. Je n'ai pas besoin de mutex si je n'ai qu'un seul thread dans mon programme)
Deuxièmement, vous devez connaître la différence entre un mutex normal et un mutex récursif .
Cité de l' APUE :
(Un mutex récursif est a) Un type de mutex qui permet au même thread de le verrouiller plusieurs fois sans le déverrouiller au préalable.
La principale différence est que dans le même fil , le reverrouillage d'un verrou récursif ne conduit pas à un blocage, ni ne bloque le thread.
Cela signifie-t-il que le verrouillage récursif ne provoque jamais de blocage?
Non, cela peut toujours provoquer un blocage en tant que mutex normal si vous l'avez verrouillé dans un thread sans le déverrouiller et essayez de le verrouiller dans d'autres threads.
Voyons du code comme preuve.
- mutex normal avec blocage
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t lock;
void * func1(void *arg){
printf("thread1\n");
pthread_mutex_lock(&lock);
printf("thread1 hey hey\n");
}
void * func2(void *arg){
printf("thread2\n");
pthread_mutex_lock(&lock);
printf("thread2 hey hey\n");
}
int main(){
pthread_mutexattr_t lock_attr;
int error;
// error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);
if(error){
perror(NULL);
}
pthread_mutex_init(&lock, &lock_attr);
pthread_t t1, t2;
pthread_create(&t1, NULL, func1, NULL);
pthread_create(&t2, NULL, func2, NULL);
pthread_join(t2, NULL);
}
production:
thread1
thread1 hey hey
thread2
exemple commun de blocage, pas de problème.
- mutex récursif avec blocage
Décommentez simplement cette ligne
error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
et commentez l'autre.
production:
thread1
thread1 hey hey
thread2
Oui, le mutex récursif peut également provoquer un blocage.
- mutex normal, reverrouiller dans le même thread
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t lock;
void func3(){
printf("func3\n");
pthread_mutex_lock(&lock);
printf("func3 hey hey\n");
}
void * func1(void *arg){
printf("thread1\n");
pthread_mutex_lock(&lock);
func3();
printf("thread1 hey hey\n");
}
void * func2(void *arg){
printf("thread2\n");
pthread_mutex_lock(&lock);
printf("thread2 hey hey\n");
}
int main(){
pthread_mutexattr_t lock_attr;
int error;
// error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);
if(error){
perror(NULL);
}
pthread_mutex_init(&lock, &lock_attr);
pthread_t t1, t2;
pthread_create(&t1, NULL, func1, NULL);
sleep(2);
pthread_create(&t2, NULL, func2, NULL);
pthread_join(t2, NULL);
}
production:
thread1
func3
thread2
Impasse dans thread t1
, dans func3
.
(J'utilise sleep(2)
pour rendre plus facile de voir que le blocage est d'abord causé par le reverrouillage func3
)
- mutex récursif, reverrouiller dans le même thread
Encore une fois, décommentez la ligne mutex récursive et commentez l'autre ligne.
production:
thread1
func3
func3 hey hey
thread1 hey hey
thread2
Impasse dans thread t2
, dans func2
. Voir? func3
se termine et se termine, le reverrouillage ne bloque pas le thread ou ne mène pas à un blocage.
Alors, dernière question, pourquoi en avons-nous besoin?
Pour la fonction récursive (appelée dans les programmes multi-threads et vous souhaitez protéger certaines ressources / données).
Par exemple, vous avez un programme multi-thread et appelez une fonction récursive dans le thread A. Vous avez des données que vous souhaitez protéger dans cette fonction récursive, vous utilisez donc le mécanisme mutex. L'exécution de cette fonction est séquentielle dans le thread A, donc vous reverrouilleriez définitivement le mutex en récursivité. L'utilisation d'un mutex normal provoque des blocages. Et mutex résursif est inventé pour résoudre ce problème.
Voir un exemple de la réponse acceptée
Quand utiliser le mutex récursif? .
Le Wikipedia explique très bien le mutex récursif. Vaut vraiment le détour. Wikipédia: Reentrant_mutex