2010-12-06 16 views
13

necesito para ver si un mutex está bloqueado o desbloqueado en una sentencia if por lo verifico así ...Compruebe si un mutex pthread está bloqueado o desbloqueado (Después de un hilo ha encerrado en sí mismo)

if(mutex[id] != 2){ 
    /* do stuff */ 
} 

pero cuando compruebo que gcc me da el siguiente error:

error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')

Entonces, ¿cómo puedo comprobar para ver si el mutex está bloqueado o no?

EDIT:

Un componente clave de mi problema es que mis hilos (por diseño) se encierran derecha después de pasar el control a otro hilo. Entonces, cuando el hilo A pasa el control al hilo B, el hilo A está bloqueado, el hilo B hace algunas cosas, luego cuando el hilo B está listo, desbloqueará el hilo A.

El problema es que si el hilo B intenta desbloquear el hilo A y el subproceso A aún no se ha completado el bloqueo, la llamada para desbloquear se pierde y el subproceso A permanece bloqueado, lo que causa un bloqueo inactivo.

ACTUALIZACIÓN:

rehice mi programa de tomar la sugerencia de la CAF, pero todavía estoy corriendo en problemas. He moldeado mi programa en la estructura de caf proporcionado lo mejor que puedo, pero ni siquiera puedo decir lo que está causando el bloqueo muerto ahora ... He creado una nueva pregunta here en busca de ayuda con mi código.

A continuación se muestra una versión ejecutable de la sugerencia de caf. Hice un pequeño reordenamiento en la función para el hilo a, sin el cual tanto el hilo a como el hilo b se habrían bloqueado en su creación, esperando una condición que nunca podría cambiar.

#include <pthread.h> 

int run_a = 0; 
pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER; 

int run_b = 0; 
pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER; 

void *a(void *); 
void *b(void *); 

int main(){ 
    int status; 
    pthread_t thread_a; 
    pthread_t thread_b; 

    pthread_create(&thread_a, NULL, a, (void *)0); 
    pthread_create(&thread_b, NULL, b, (void *)0); 

    pthread_join(thread_a, (void **)&status); 
    pthread_join(thread_b, (void **)&status); 

} 

/* thread A */ 
void *a(void *i){ 
    while (1) { 
     printf("thread A is running\n"); 
     sleep(1); 

     /* unlock thread B */ 
     pthread_mutex_lock(&lock_b); 
      run_b = 1; 
      pthread_cond_signal(&cond_b); 
     pthread_mutex_unlock(&lock_b); 

     /* wait for thread A to be runnable */ 
     pthread_mutex_lock(&lock_a); 
      while (!run_a) 
       pthread_cond_wait(&cond_a, &lock_a); 
      run_a = 0; 
     pthread_mutex_unlock(&lock_a);  
    } 
} 

/* thread B */ 
void *b(void *i){ 
    while (1) { 
     /* wait for thread B to be runnable */ 
     pthread_mutex_lock(&lock_b); 
      while (!run_b) 
       pthread_cond_wait(&cond_b, &lock_b); 
      run_b = 0; 
     pthread_mutex_unlock(&lock_b); 

     printf("thread B is running\n"); 
     sleep(1); 

     /* unlock thread A */ 
     pthread_mutex_lock(&lock_a); 
      run_a = 1; 
      pthread_cond_signal(&cond_a); 
     pthread_mutex_unlock(&lock_a); 
    } 
} 
+0

Una nota rápida, los mutexes deben ser desbloqueados por el hilo que los bloqueó. Si desea una construcción de bloqueo que pueda ser bloqueada por un hilo y desbloqueada por otro, debe usar semáforos (o construir su propio semáforo como se muestra en el ejemplo anterior). Pueden surgir errores de sincronización realmente desagradables si un hilo bloquea un mutx y otro lo libera –

Respuesta

16

Los mutexes no son la primitiva correcta para el esquema que desea implementar.Debería utilizar variables de condición :

int run_thread_a = 0; 
pthread_mutex_t run_lock_a = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t run_cond_a = PTHREAD_COND_INITIALIZER; 

int run_thread_b = 0; 
pthread_mutex_t run_lock_b = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t run_cond_b = PTHREAD_COND_INITIALIZER; 

/* thread A */ 
while (1) { 
    /* Wait for Thread A to be runnable */ 
    pthread_mutex_lock(&run_lock_a); 
    while (!run_thread_a) 
     pthread_cond_wait(&run_cond_a, &run_lock_a); 
    run_thread_a = 0; 
    pthread_mutex_unlock(&run_lock_a); 

    /* Do some work */ 

    /* Now wake thread B */ 
    pthread_mutex_lock(&run_lock_b); 
    run_thread_b = 1; 
    pthread_cond_signal(&run_cond_b); 
    pthread_mutex_unlock(&run_lock_b); 
} 

/* thread B */ 
while (1) { 
    /* Wait for Thread B to be runnable */ 
    pthread_mutex_lock(&run_lock_b); 
    while (!run_thread_b) 
     pthread_cond_wait(&run_cond_b, &run_lock_b); 
    run_thread_b = 0; 
    pthread_mutex_unlock(&run_lock_b); 

    /* Do some work */ 

    /* Now wake thread A */ 
    pthread_mutex_lock(&run_lock_a); 
    run_thread_a = 1; 
    pthread_cond_signal(&run_cond_a); 
    pthread_mutex_unlock(&run_lock_a); 
} 

Cada hilo bloqueará en pthread_cond_wait() hasta que las otras señales de rosca a despertar. Esto no será un punto muerto.

Se puede extender fácilmente a muchos hilos, asignando un int, pthread_cond_t y pthread_mutex_t por hilo.

+0

@caf Intenté originalmente usar una condición, pero mis hilos deben ejecutarse al mismo tiempo, y a menos que quiera hacer una condición para cada uno (una serie de condiciones no funcionarán porque se bloquearía cada vez que se accediera por alguna hilo, eliminando así la concurrencia deseada) No veo cómo puedo hacer que esto funcione. – ubiquibacon

+0

@typoknig: una serie de condiciones es exactamente lo que necesita. No se "bloqueará cada vez que se acceda por un hilo". Cada variable de condición es independiente, no importa si las mantiene en una matriz o en grupos separados denominados globales. – caf

+0

@caf He actualizado mi pregunta y agregado mi código, tal vez podría echarle un vistazo. Sé que la estructura que ha sugerido es correcta, pero todavía no puedo hacer que funcione correctamente (vea la pregunta actualizada). El código que publiqué está completamente reescrito desde que hice mi pregunta (ahora usando la condición). – ubiquibacon

18

Puede usar pthread_mutex_trylock. Si eso tiene éxito, el mutex no fue reclamado y usted ahora lo posee (por lo que debe liberarlo y devolver "no guardado", en su caso). De lo contrario, alguien lo está sosteniendo.

Tengo que hacer hincapié en que "verifique si un mutex no se reclama" es una muy mala idea. Hay condiciones de carrera inherentes en este tipo de pensamiento. Si tal función le dice en el momento t que no se muestra el bloqueo, eso no dice absolutamente nada sobre si otro hilo adquirió o no el bloqueo en t+1.

En caso de que esto es mejor ilustrado con un ejemplo de código, tenga en cuenta:

bool held = is_lock_held(); 

if (!held) 
{ 
    // What exactly can you conclude here? Pretty much nothing. 
    // It was unheld at some point in the past but it might be held 
    // by the time you got to this point, or by the time you do your 
    // next instruction... 
} 
+0

@asveikau Mi problema es que tengo un hilo (a) que pasa el control a otro hilo (b) y luego se bloquea. Una vez que se realiza el thread 'b', se desbloquea el thread' a' y luego se bloquea. El sistema funciona muy bien, pero en raras ocasiones el hilo 'b'" desbloquea "el hilo' a' antes de que el hilo 'a' se bloquee, por lo que se pierde el" desbloqueo "y el programa queda bloqueado. He intentado usar 'trylock' pero no de la manera que sugeriste ... Lo intentaré de nuevo. – ubiquibacon

+0

@typoknig - Parece que debería considerar un esquema de sincronización más simple. Por ejemplo, podría hacer que B señalice un semáforo que A espera. – asveikau

+0

@asveikau el problema es que el subproceso A tiene control y debe bloquearse, y no tengo control sobre qué tan rápido se bloquea. B marca/desbloquea el semáforo para el hilo A, cuando se realiza el hilo B, pero si el hilo A todavía no se ha bloqueado (y lo hace después de que el hilo B ha señalado el desbloqueo), el hilo A permanecerá bloqueado. – ubiquibacon

0

No se puede comparar un pthread_mutex_t con un int.

Puede utilizar

int pthread_mutex_trylock(pthread_mutex_t *mutex);

para comprobar que.

Cuestiones relacionadas