Pithikos
Estoy un poco confundido sobre cómo declarar un mutex recursivo usando pthread. Lo que trato de hacer es tener solo un subproceso a la vez para poder ejecutar un fragmento de código (incluidas las funciones), pero después del escepticismo descubrí que el uso de mutexes no funcionaría y que, en su lugar, debería usar mutexes recursivos. Aquí está mi código:
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
Entonces, lo que trato de hacer es simplemente leer/eliminar de la cola en serie.
La cuestión es que no hay ningún ejemplo sobre cómo declarar mutex recursivos. O tal vez hay algunos, pero no se compilan para mí.
Piotr Kukielka
El código de Michael Foukarakis es casi bueno, pero inicializa el mutex dos veces, lo que conduce a un comportamiento indefinido. Debería ser simplemente:
pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;
pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr);
De hecho, uso este código en producción y sé que funciona correctamente en Linux, Solaris, HP-UX, AIX, Mac OSX y FreeBSD.
También debe agregar el indicador de vinculación adecuado para compilar esto:
AIX, Linux, FreeBSD:
CPLATFORM += -pthread
mingw32:
LDFLAGS += -lpthread
-
Algunos sistemas requieren agregar
#define _GNU_SOURCE
(de lo contrario, un compilador lanza declaración implícita)– Mitrakov Artem
20 de enero de 2016 a las 13:18
-
Me estoy poniendo:
main.c:4:24: error: expected declaration specifiers or ‘...’ before ‘&’ token pthread_mutexattr_init(&Attr);
– Shawn Anderson
26 de enero de 2018 a las 0:25
-
esto necesita
pthread_mutexattr_destroy(&Attr)
al final o de lo contrario estarás perdiendo memoria.– PoVa
3 de enero de 2019 a las 9:15
Michael Foukarakis
Para crear un mutex recursivo, puede usar:
#include <pthread.h>
/* Don't forget to check the return value! */
int pthread_mutexatttr_settype(pthread_mutexattr_t *attr,
int type);
donde esta el tipo PTHREAD_MUTEX_RECURSIVE
o un inicializador.
Por ejemplo:
/* ..or PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t mta;
o alternativamente, inicialice en tiempo de ejecución (no haga ambas cosas, es un comportamiento indefinido):
pthread_mutexattr_init(&mta);
/* or PTHREAD_MUTEX_RECURSIVE_NP */
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex, &mta);
-
Recibo el error que obtuve en mis intentos anteriores. Las líneas que no compilan son las tres últimas y uso GCC con el indicador -pthread. pthread.h también está incluido.
– Pithikos
12 de agosto de 2011 a las 8:49
-
¿Qué error? Nunca mencionaste uno. De todos modos, verifique la respuesta actualizada.
–Michael Foukarakis
12 de agosto de 2011 a las 8:52
-
Sí, ¿qué error y qué sistema operativo? Solaris requiere [g]cc -mt para aplicaciones de subprocesos múltiples. Algunas implementaciones de “pthreads” no son 100% compatibles con POSIX.
– jim mcnamara
31 de octubre de 2011 a las 14:47
En Linux (pero esto no es portátil para otros sistemas), si el mutex es una variable global o estática, puede inicializarlo como
static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
(y por cierto, el ejemplo es de pthread_mutex_init(3)
hombre páginas!)
-
Gracias por la info. Por lo tanto, encontré en MAC que es: static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
– Vale
11 de noviembre de 2014 a las 8:46
Debe agregar atributos de exclusión mutua al crear la exclusión mutua.
Llamar pthread_mutexattr_init
entonces pthread_mutexattr_settype
con PTHREAD_MUTEX_RECURSIVE
luego use estos atributos con pthread_mutex_init
. Leer man pthread_mutexattr_init
para más información.
No necesita mutex recursivos para resolver esto. El ejemplo que has dado está bien, siempre y cuando el mismo
mutex
se utiliza para todos los subprocesos que accedenqueue
. Por este motivo, lo habitual sería incluir el mutex dentro de la propia cola:pthread_mutex_lock(&mutex->queue);
o si la cola es una estructura de datos opaca,queue_lock(queue);
(dóndequeue_lock()
bloquea el mutex internamente).– café
12 de agosto de 2011 a las 9:08
Uno de los gurús detrás de pthreads, David Butenhof, tiene una divertida diatriba mutex recursiva en zaval.org/resources/library/butenhof1.html . Así que sí, los mutex recursivos suelen ser una indicación de un diseño defectuoso.
– janneb
12 de agosto de 2011 a las 9:29
@janneb: Hay muchos usos correctos para los mutex recursivos, pero sí, recomendaría encarecidamente a un principiante que no los use…
– R.. GitHub DEJA DE AYUDAR A ICE
12 de agosto de 2011 a las 12:18
@R..: Creo que no hay tantos usos correctos para los mutex recursivos que no se pueden rediseñar para evitarlos.
–Andriy Tylychko
30 de octubre de 2011 a las 11:07
@AndyT: La clase principal de usos importantes para los mutex recursivos que conozco es cuando tiene operaciones en un recurso compartido que debe ser atómico individualmente, pero también desea permitir agrupar varias operaciones como una transacción atómica. El ejemplo clásico es stdio con
flockfile
.– R.. GitHub DEJA DE AYUDAR A ICE
30/10/2011 a las 21:48