elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Rompecabezas de Bitcoin, Medio millón USD en premios


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  PTHREADS - Programación concurrente.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: PTHREADS - Programación concurrente.  (Leído 2,909 veces)
GGZ

Desconectado Desconectado

Mensajes: 144



Ver Perfil
PTHREADS - Programación concurrente.
« en: 6 Mayo 2017, 21:21 pm »

Código
  1. #include <stdio.h>
  2. #include <pthread.h>
  3.  
  4. pthread_mutex_t MyMutex = PTHREAD_MUTEX_INITIALIZER;
  5. pthread_cond_t seguir2 = PTHREAD_COND_INITIALIZER;
  6. pthread_cond_t seguir = PTHREAD_COND_INITIALIZER;
  7.  
  8. #define N 5
  9.  
  10. int aloja = 0;
  11. int sigo = 0;
  12.  
  13.  
  14.  
  15. /*
  16. Cuando un thread -que debe tener el mutex ya tomado- llama a wait(), suelta el mutex y
  17. entra en espera bloqueante.
  18.  
  19. DEBE TENER EL MUTEX YA TOMADO!
  20.  
  21.  
  22.  
  23. Cuando un thread llama a signal(), otro thread en espera, de haberlo, se despierta de su wait()
  24. CON EL MUTEX YA ADQUIRIDO
  25.  
  26. CON EL MUTEX YA ADQUIRIDO!
  27.  
  28. */
  29.  
  30. void *freno (void *a)
  31. {
  32. for (;;){
  33.  
  34. // Tomo el mutex.
  35. pthread_mutex_lock(&MyMutex);
  36.  
  37. // Hey!, quiero entrar, terminá lo que estás haciendo, te espero.
  38. aloja = 1;
  39.  
  40. // Espero hasta que se "apague" la función avanzar.
  41. // Cuando se apaga, AUTOMATICAMENTE TOMO YO EL MUTEX!!
  42. while (sigo != 0){printf ("me llego la señal.\n"); pthread_cond_wait(&seguir,&MyMutex);}
  43.  
  44. // Si llegué hasta acá es porque yo tengo el mutex nadie mas lo puede tomar.
  45. printf ("Estoy en freno\n");
  46.  
  47. // Terminé de hacer todo lo que quería hacer.
  48. aloja = 0; // Por más que lo ponga el 0, "avanzar" no puede entrar todavía, porque
  49. // yo tengo el mutex!
  50.  
  51.  
  52. /* Libero el mutex, es decir, ahora la función avanzar sí puede tomar el mutex, PERO
  53. a la vez no ya que está dentro de un wait esperando un SIGNAL no que libere un mutex.
  54. Aunque no está demás recordar que solo 1 puede tomar el mutex a la vez. */
  55. pthread_mutex_unlock(&MyMutex);
  56.  
  57. /*
  58. Cuando un thread llama a signal(), otro thread en espera, de haberlo, se despierta de su wait
  59. CON EL MUTEX YA TOMADO!
  60.  
  61. pthread_cond_signal(&seguir2);
  62.  
  63. */
  64.  
  65. /*
  66. Cuando un thread llama a broadcast(), todos los threads en espera, de haberlo, se despiertan de su
  67. wait CON EL MUTEX YA TOMADO, es decir en este caso, se pelean por quien toma el mutex.
  68. */
  69.  
  70. pthread_cond_broadcast(&seguir2);
  71. }
  72. }
  73.  
  74.  
  75. void *avanzar (void *b)
  76. {
  77. for (;;){
  78. // Tomo yo el mutex, nadie más lo puede tomar.
  79. pthread_mutex_lock(&MyMutex);
  80. sigo++;
  81. // Libero, ahora si puede tomar el mutex la función "freno".
  82. pthread_mutex_unlock(&MyMutex);
  83.  
  84. //sleep(3);
  85. printf ("estoy en sigo.\n");
  86.  
  87. // No puedo tomar el mutex hasta que la función freno recién llegue a la linea donde entra en espera!
  88. pthread_mutex_lock(&MyMutex);
  89. sigo--;
  90. // Libero el mutex, recien ahora pueden ejecutarse más funciones "freno", antes no porque yo tenía el
  91. // mutex tomado.
  92. pthread_mutex_unlock(&MyMutex);
  93.  
  94. printf("Avanzar: %d\n",sigo);
  95.  
  96. /* Esta señal está esperando "freno" para poder continuar, pero además de esperar la señal espera
  97. también que la cantidad de "sigo" sea igual a 0 */
  98.  
  99. /*
  100. Si sigo es un número mayor a 0, entonces de todos modos va a seguir esperando.
  101. */
  102. pthread_cond_signal(&seguir);
  103.  
  104. /*PERO! a la vez yo me bloqueo. Esperando ahora que "freno" me desbloque. */
  105. /* Y a su vez freno está esperando que yo lo desbloquee. */
  106. while (aloja != 0)pthread_cond_wait(&seguir2,&MyMutex);
  107.  
  108. /*
  109. ¿Qué pasaría si avanzar toma el mutex e incrementa en 1 la variable "sigo" y al toque "freno" pone
  110. en 1 la variable aloja?
  111.  
  112. Lo que pasaría es que la variable sigo se incrementa luego suelta el mutex, lo toma la función"freno"
  113. pone en 1 aloja pero como sigo es mayor que cero entonces SUELTA el mutex automáticamente y deja
  114. que siga funcionando "avanzar", entonces pueden pasar cosas!:
  115.  
  116. Primero de todo, no se pueden ejecutar dos "frenos" a a la vez pero si se pueden ejecutar "avanzar"
  117. muchas veces.
  118.  
  119. Entonces, avanzar toma el mutex y decrementa en 1 la variable
  120. sigo y al momento lo suelta, PERO "freno" todavía no puede hacer nada porque está esperando un
  121. signal,  no está esperando que suelte el mutex (explicado anteriormente)
  122.  
  123. Entonces yo le doy el signal y suponiendo que el numero de sigo es igual a 0, se ejecuta freno y yo
  124. entro en espera hasta que freno termine.
  125.  
  126.  
  127. */
  128. }
  129.  
  130. }
  131.  
  132. int main (void)
  133. {
  134. int i;
  135. pthread_t prueba1[N],prueba2[N];
  136.  
  137. for (i=0; i<N; i++){
  138. pthread_create(&prueba1[i],0,freno,"aloja");
  139. pthread_create(&prueba2[i],0,avanzar,"chau");
  140. }
  141.  
  142. pthread_join(prueba1[0],0);
  143. return 0;
  144. }
  145.  

El programa sigue está logica aunque las funciones no se llamen lector y escritor.

1. No puede haber un lector accediendo al arreglo al mismo tiempo que un escritor.
2. Varios lectores pueden acceder al arreglo simult´aneamente.
3. S´olo puede haber un escritor a la vez.

Y además cuando los lectores que están leyendo terminen su lectura pero no se puedan empezar nuevas lecturas hasta que el escritor escriba.

freno = escritor.
avanzar = lector.

Aunque en este caso no escriben ni leen nada solo muestran texto.

El problema es que no funciona y no sé que es lo que estoy pensando mal, el programa se congela es decir en algún momento queda esperando algo que nunca llega.



« Última modificación: 6 Mayo 2017, 21:34 pm por GGZ » En línea

LET'S DO STUFF!!
ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: PTHREADS - Programación concurrente.
« Respuesta #1 en: 7 Mayo 2017, 02:42 am »

Un detalle importante: Ponle mutex a los printf.

Y luego pues... Intenta darle un enfoque práctico al programa. A ti te puede ser más fácil visualizarlo así, y desde luego, a nosotros también (decir que es como un lector y un escritor no ayuda mucho).

Especifica qué quieres que haga el programa exactamente, y entonces será más fácil verlo.


En línea

GGZ

Desconectado Desconectado

Mensajes: 144



Ver Perfil
Re: PTHREADS - Programación concurrente.
« Respuesta #2 en: 7 Mayo 2017, 04:43 am »

Lo solucioné así:

Código
  1. #include <stdio.h>
  2. #include <pthread.h>
  3.  
  4. #define N 15
  5. #define ARRLEN 1024
  6.  
  7. pthread_mutex_t MyMutex = PTHREAD_MUTEX_INITIALIZER;
  8. pthread_cond_t seguir = PTHREAD_COND_INITIALIZER;
  9. pthread_cond_t seguir2 = PTHREAD_COND_INITIALIZER;
  10.  
  11. int arr[ARRLEN];
  12.  
  13. /* Cantidad de funciones "lectores" que se están ejecutando.*/
  14. int lectores = 0;
  15. /* Variable utilizada por si quiero escribir.*/
  16. int wannawrite = 0;
  17.  
  18.  
  19. void *escritor(void *arg)
  20. {
  21.  int i;
  22.  int num = *((int *)arg);
  23.  for (;;) {
  24.    /*
  25.        Escribo el mutex al principio y este está tomando toda la función porque no pueden
  26.        haber más de 1 escritor a la vez.
  27.     */
  28.    pthread_mutex_lock(&MyMutex);
  29.  
  30.    /* Hey!!, quiero escribir!!, ahora todos deben dormir hasta que termine de escribir.*/
  31.    wannawrite = 1;
  32.  
  33.    /* Espero hasta que todos los que estan leyendo, terminen de leer y se pogan a dormir
  34.        De no ser así libero el mutex.
  35.  
  36.        wait(): Si tiene la señal, entonces despierta con EL MUTEX YA ADQUIRIDO.
  37.     */
  38.    while (lectores != 0) pthread_cond_wait(&seguir,&MyMutex);
  39.  
  40.    /* sleep(random()%3); */
  41.    for (i=0; i<ARRLEN; i++) {
  42.      arr[i] = num;
  43.    }
  44.  
  45.    /* Terminé de escribir. */
  46.    wannawrite = 0;
  47.  
  48.    /* Heeyy!!, despertá todos los lectores que tuvieron que dormir para que pueda escribir.*/
  49.  
  50.    pthread_cond_broadcast(&seguir2);
  51.    pthread_mutex_unlock(&MyMutex);
  52.  }
  53.  return NULL;
  54. }
  55.  
  56. void *lector(void *arg)
  57. {
  58.  int v, i, err;
  59.  int num = *((int *)arg);
  60.  for (;;) {
  61.    /* En este caso si pueden haber más lectores a la vez entonces no voy a bloquear toda la función con un mutex,
  62.      solo la bloquearé por partes. */
  63.  
  64.    pthread_mutex_lock(&MyMutex);
  65.    lectores++;
  66.    pthread_mutex_unlock(&MyMutex);
  67.  
  68.    /* sleep(random()%3); */
  69.    err = 0;
  70.    v = arr[0];
  71.    for (i=1; i<ARRLEN; i++) {
  72.      if (arr[i]!=v) {
  73.        err=1;
  74.        break;
  75.      }
  76.    }
  77.    if (err) printf("Lector %d, error de lectura\n", num);
  78.    else printf("Lector %d, dato %d\n", num, v);
  79.  
  80.    pthread_mutex_lock(&MyMutex);
  81.    lectores--;
  82.  
  83.    /* si pondría un unlock acá, podría pasar cualquier cosa hasta que mande
  84.        la señal de que yo terminé de leer y luego esperar. Por eso el unlock lo pongo al final.
  85.        Si yo tengo el mutex por más que el otro tenga la señal y los lectores sean 0
  86.        no puede tomar el mutex por lo tanto se queda bloqueado hasta que lo libero.  */
  87.  
  88.    /* Mando una señal que un thread terminó de leer. */
  89.    pthread_cond_signal(&seguir);
  90.  
  91.    /* Si quiere escribir, entonces me bloqueo hasta que me avise que terminó de escribir.*/
  92.    while(wannawrite == 1) pthread_cond_wait(&seguir2,&MyMutex);
  93.  
  94.    /* Ahora si suelto el mutex.*/
  95.    pthread_mutex_unlock(&MyMutex);
  96.  
  97.  }
  98.  return NULL;
  99. }
  100.  
  101. int main()
  102. {
  103.  int i;
  104.  pthread_t lectores[N], escritores[N];
  105.  int arg[N];
  106.  
  107.  for (i=0; i<ARRLEN; i++) {
  108.    arr[i] = -1;
  109.  }
  110.  for (i=0; i<N; i++) {
  111.    arg[i] = i;
  112.    pthread_create(&lectores[i], NULL, lector, (void *)&arg[i]);
  113.    pthread_create(&escritores[i], NULL, escritor, (void *)&arg[i]);
  114.  }
  115.  pthread_join(lectores[0], NULL); /* Espera para siempre */
  116.  return 0;
  117. }
  118.  

De todos modos esta solución le da demasiada prioridad a los escritores que a los lectores, no sé por qué se debe eso.

¿Alguna idea?
« Última modificación: 7 Mayo 2017, 06:54 am por GGZ » En línea

LET'S DO STUFF!!
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Programacion concurrente
Ejercicios
omykron 0 3,733 Último mensaje 23 Enero 2007, 07:47 am
por omykron
PROGRAMACION CONCURRENTE
Java
maii210890 0 2,652 Último mensaje 11 Abril 2013, 01:55 am
por maii210890
Libros programacion concurrente?
Programación General
JavierJV 1 3,276 Último mensaje 1 Octubre 2013, 19:34 pm
por Ragnarok
Programación Concurrente (Intro)
Programación General
edr89 4 3,538 Último mensaje 28 Diciembre 2014, 01:25 am
por edr89
Conceptos de Programación Concurrente
Programación General
edr89 0 1,786 Último mensaje 25 Enero 2015, 03:17 am
por edr89
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines