Comunicacion entre hilos. Consumidor-Productor

Iniciado por SDCC, 2 Octubre 2019, 21:05 PM

0 Miembros y 1 Visitante están viendo este tema.

SDCC

Buenas a todos, encontre un ejemplo del problema de comunicacion en el libro de Tanenbaum que es el siguiente:


#include <stdio.h>
#include <pthread.h>
#define MAX 100
pthread_mutex_t el_mutex;
pthread_cond_t condc,condp;
int buffer = 0;

void *productor(void *ptr){
    int i;
    for(i = 1; i <= MAX;i++){
        pthread_mutex_lock(&el_mutex);
        while(buffer != 0 ) pthread_cond_wait(&condp,&el_mutex);
        printf("Productor....\n");
        buffer = i;
        pthread_cond_signal(&condc);
        pthread_mutex_unlock(&el_mutex);
    }
    pthread_exit(0);
}


void *consumidor(void *ptr){
    int i;
    for(i = 1; i <= MAX;i++){
        pthread_mutex_lock(&el_mutex);
        while(buffer == 0 ) pthread_cond_wait(&condc,&el_mutex);
        printf("Consumidor....\n");
        buffer = 0;
        pthread_cond_signal(&condp);
        pthread_mutex_unlock(&el_mutex);
    }
    pthread_exit(0);

}


int main(){
    pthread_t pro,con;
    pthread_mutex_init(&el_mutex,0);
    pthread_cond_init(&condc,0);
    pthread_cond_init(&condp,0);
    pthread_create(&con,0,consumidor,0);
    pthread_create(&pro,0,productor,0);
    pthread_join(pro,0);
    pthread_join(con,0);
    pthread_cond_destroy(&condc);
    pthread_cond_destroy(&condp);
    pthread_mutex_destroy(&el_mutex);
    return 0;

}


Todo va bien hasta aqui.Mi pregunta es si tiene sentido esta dos lineas:

        while(buffer != 0 ) pthread_cond_wait(&condp,&el_mutex);



        while(buffer == 0 ) pthread_cond_wait(&condc,&el_mutex);


¿Es necesario poner la condicion en un while ?. Hasta donde yo entiendo el problema podria ser resuelto sustituyendo el while por un if y lo he verificado en algunas pruebas pero no se si algun detalle se me esta escapando. Creo que el while seria util cuando se tuviera mas de un consumidor o productor pero en este caso en concreto en el cual solo es 1-1 , ¿Tiene sentido?

RayR

Sí, siempre se debe usar un while. Uno, porque el hecho de que en un caso concreto no tengas más threads esperando por el mutex no debería ser razón para no escribir un código que funcionará bien de forma general. Hacer lo correcto en este caso consiste en algo tan simple usar un while, por lo que no se justifica no hacerlo. Otra razón es que es posible que un thread de pronto despierte de forma errónea, aunque la condición no se haya satisfecho realmente. Esta posibilidad ni siquiera se considera necesariamente un bug, pues está contemplada dentro de la especificación de UNIX. Esto es por limitaciones técnicas de ciertos sistemas, me parece. Es muy difícil que en la práctica te vayas a encontrar con un caso así, pero de nuevo, lo correcto es escribir código que (en teoría, al menos) funcione siempre bien.

dijsktra

#2
Cita de: RayR en  2 Octubre 2019, 21:47 PM
Sí, siempre se debe usar un while...[...]
La respuesta de RayR es muy acertada.

Como norma general, hay que poner while. Sólo analizando un caso particular puedes poner if con seguridad, pero tampoco se gana tanto en eficiencia...

Si te lia tu "intuición operacional", (ya que, si es difícil la programación secuencial, la concurrente es inabordable por la explosión de estados) de te recomiendo el siguiente esquema en pseudo lenguaje


(one thread)
<await B(var) -> S>

(other thread)
<var = e>

Se traduce en C a lo que refleja el código :

(one thread)
pthread_Mutex_lock(l)
while !b do pthread_cond_wait(l, c) ;
S
pthread_Mutex_unlock(l)

(other thread)
pthread_Mutex_lock(l)
var=e
pthread_cond_signal(c)
pthread_Mutex_unlock(l)


Por último, antes de manejar variables de condición en C, estudia teoría de monitores en papel y pseudo código! Las variables de condición y mutex asociados no se pueden comprender sin ellos. Fueron creados para implementar esa idea, aunque el lenguaje C no los implementa directamente. java, por ejemplo, si, pero se una forma muy limitada).

la gente las utiliza sin saber su razón de ser
(Perdón por la imprecision, pero estoy escribiendo dese un móvil)
Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)