C: Wie deklariert man einen rekursiven Mutex mit POSIX-Threads?

Lesezeit: 4 Minuten

Benutzeravatar von Pithikos
Pithikos

Ich bin etwas verwirrt darüber, wie man einen rekursiven Mutex mit pthread deklariert. Was ich versuche, ist, dass jeweils nur ein Thread einen Code (einschließlich Funktionen) ausführen kann, aber nach Skepsis habe ich herausgefunden, dass die Verwendung von Mutexes nicht funktionieren würde und dass ich stattdessen rekursive Mutexe verwenden sollte. Hier ist mein 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

Also, was ich versuche zu tun, ist einfach seriell aus der Warteschlange zu lesen/entfernen.

Die Sache ist, dass es da draußen kein Beispiel dafür gibt, wie man rekursive Mutexe deklariert. Oder es gibt vielleicht ein paar, aber sie kompilieren nicht für mich.

  • Sie benötigen keine rekursiven Mutexe, um dies zu lösen. Das Beispiel, das Sie gegeben haben, ist in Ordnung, solange es dasselbe ist mutex wird für alle Threads verwendet, die darauf zugreifen queue. Aus diesem Grund wäre es üblich, den Mutex in die Warteschlange selbst aufzunehmen: pthread_mutex_lock(&mutex->queue);oder wenn die Warteschlange eine undurchsichtige Datenstruktur ist, queue_lock(queue); (wo queue_lock() sperrt den Mutex intern).

    – Café

    12. August 2011 um 9:08 Uhr

  • Einer der Gurus hinter pthreads, David Butenhof, hat einen amüsanten rekursiven Mutex-Geschwätz zaval.org/resources/library/butenhof1.html . Also ja, rekursive Mutexe sind normalerweise ein Hinweis auf ein fehlerhaftes Design.

    – janeb

    12. August 2011 um 9:29 Uhr

  • @janneb: Es gibt viele korrekte Verwendungen für rekursive Mutexe, aber ja, ich würde einem Anfänger dringend davon abraten …

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    12. August 2011 um 12:18 Uhr

  • @R ..: Ich denke, es gibt nicht so viele korrekte Verwendungen für rekursive Mutexe, die nicht neu gestaltet werden können, um sie zu vermeiden.

    – Andriy Tylychko

    30. Oktober 2011 um 11:07 Uhr

  • @AndyT: Die Hauptklasse wichtiger Anwendungen für rekursive Mutexe, die ich kenne, ist, wenn Sie Operationen auf einer gemeinsam genutzten Ressource haben, die einzeln atomar sein müssen, aber auch das Gruppieren mehrerer Operationen als atomare Transaktion zulassen möchten. Das klassische Beispiel ist stdio with flockfile.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    30. Oktober 2011 um 21:48 Uhr

Benutzeravatar von Piotr Kukielka
Piotr Kukielka

Der Code von Michael Foukarakis ist fast gut, aber er initialisiert den Mutex zweimal, was zu undefiniertem Verhalten führt. Es sollte nur sein:

pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;

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

Ich verwende diesen Code tatsächlich in der Produktion und ich weiß, dass er unter Linux, Solaris, HP-UX, AIX, Mac OSX und FreeBSD korrekt funktioniert.

Sie müssen auch das richtige Linker-Flag hinzufügen, um dies zu kompilieren:

AIX, Linux, FreeBSD:
CPLATFORM += -pthread

mingw32:
LDFLAGS += -lpthread

  • Einige Systeme müssen hinzugefügt werden #define _GNU_SOURCE (Andernfalls wirft ein Compiler implizite Deklaration)

    – Mitrakow Artjom

    20. Januar 2016 um 13:18 Uhr

  • Ich erhalte: main.c:4:24: error: expected declaration specifiers or ‘...’ before ‘&’ token pthread_mutexattr_init(&Attr);

    – Shawn Anderson

    26. Januar 2018 um 0:25 Uhr

  • Das braucht pthread_mutexattr_destroy(&Attr) am Ende, oder Sie werden Speicher verlieren.

    – PoVa

    3. Januar 2019 um 9:15 Uhr


Benutzeravatar von Michael Foukarakis
Michael Foukarakis

Um einen rekursiven Mutex zu erstellen, können Sie entweder verwenden:

#include <pthread.h>
/* Don't forget to check the return value! */
int pthread_mutexatttr_settype(pthread_mutexattr_t *attr,
                               int type);

wo Typ ist PTHREAD_MUTEX_RECURSIVEoder ein Initialisierer.

Zum Beispiel:

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

oder alternativ zur Laufzeit initialisieren (nicht beides tun, es ist undefiniertes Verhalten):

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

pthread_mutex_init(&mutex, &mta);

  • Ich bekomme den Fehler, den ich in meinen früheren Versuchen bekommen habe. Die Zeilen, die nicht kompiliert werden, sind die drei letzten, und ich verwende GCC mit dem Flag -pthread. pthread.h ist ebenfalls enthalten.

    – Pithikos

    12. August 2011 um 8:49 Uhr

  • Welcher Fehler? Du hast nie einen erwähnt. Überprüfen Sie auf jeden Fall die aktualisierte Antwort.

    – Michael Foukarakis

    12. August 2011 um 8:52 Uhr


  • Ja, welcher Fehler tatsächlich und welches Betriebssystem? Solaris erfordert [g]cc -mt für Multithread-Anwendungen. Einige Implementierungen von “pthreads” sind nicht 100 % POSIX-kompatibel.

    – Jim Mcnamara

    31. Oktober 2011 um 14:47 Uhr

Wenn der Mutex unter Linux (aber nicht auf andere Systeme portierbar) eine globale oder statische Variable ist, können Sie ihn wie folgt initialisieren

static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

(Das Beispiel stammt übrigens von pthread_mutex_init(3) Mann Seiten!)

  • Danke für die Information. So fand ich auf MAC es ist: static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;

    – Val

    11. November 2014 um 8:46 Uhr

Beim Erstellen des Mutex müssen Sie Mutex-Attribute hinzufügen.

Anruf pthread_mutexattr_initdann pthread_mutexattr_settype mit PTHREAD_MUTEX_RECURSIVE Verwenden Sie dann diese Attribute mit pthread_mutex_init. Lesen man pthread_mutexattr_init Für mehr Information.

1411640cookie-checkC: Wie deklariert man einen rekursiven Mutex mit POSIX-Threads?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy