web-dev-qa-db-fra.com

C: Comment déclarez-vous un mutex récursif avec des threads POSIX?

Je suis un peu confus sur la façon de déclarer un mutex récursif en utilisant pthread. Ce que j'essaie de faire, c'est de n'avoir qu'un seul thread à la fois pour exécuter un morceau de code (y compris les fonctions) mais après scepticisme, j'ai compris que l'utilisation de mutex ne fonctionnerait pas et qu'au lieu de cela, je devrais utiliser des mutex récursifs. Voici mon code:

pthread_mutex_lock(&mutex);                   // LOCK

item = queue_peek(queue);                     // get last item in queue
item_buff=item;                               // save item to a buffer
queue_removelast(queue);                      // remove last item from queue

pthread_mutex_unlock(&mutex);                 // UNLOCK

Donc, ce que j'essaie de faire est simplement de lire/supprimer de la file d'attente en série.

Le fait est qu'il n'y a aucun exemple sur la façon de déclarer des mutex récursifs. Ou il y en a peut-être quelques-uns mais ils ne compilent pas pour moi.

45
Pithikos

Le code de Michael Foukarakis est presque bon mais il initialise le mutex deux fois ce qui conduit à un comportement indéfini. Cela devrait simplement être:

pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;

pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr);

J'utilise en fait ce code en production et je sais qu'il fonctionne correctement sous Linux, Solaris, HP-UX, AIX, Mac OSX et FreeBSD.

Vous devez également ajouter un indicateur de l'éditeur de liens approprié pour compiler ceci:

AIX, Linux, FreeBSD:
CPLATFORM += -pthread

mingw32:
LDFLAGS += -lpthread
80
Piotr Kukielka

Pour créer un mutex récursif, utilisez:

#include <pthread.h>
int pthread_mutexatttr_settype(pthread_mutexattr_t *attr,
                               int type);

où type est PTHREAD_MUTEX_RECURSIVE.

N'oubliez pas de vérifier la valeur de retour!

Exemple:

/* or PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
pthread_mutex_t       mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t   mta;

ou bien, initialisez à l'exécution (ne faites pas les deux, c'est un comportement indéfini):

pthread_mutexattr_init(&mta);
/* or PTHREAD_MUTEX_RECURSIVE_NP */
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);

pthread_mutex_init(&mutex, &mta);
16
Michael Foukarakis

Sous Linux (mais ce n'est pas portable sur d'autres systèmes), si le mutex est une variable globale ou statique, vous pouvez l'initialiser comme

static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

(et soit dit en passant, l'exemple provient de pthread_mutex_init(3)homme pages!)

14

Vous devez ajouter des attributs mutex lors de la création du mutex.

Appel pthread_mutexattr_init, puis pthread_mutexattr_settype avec PTHREAD_MUTEX_RECURSIVE puis utilisez ces attributs avec pthread_mutex_init. Lis man pthread_mutexattr_init pour plus d'informations.

2
hamstergene