Pagina 1 di 1

[SOLVED] Pthread - correttezza codice

Inviato: mer 14 apr 2010, 22:13
da mr.simo
Ciao a tutti, qualche mese fa studiai un po le librerie pthread e sviluppai il seguente esercizio..

Codice: Seleziona tutto

/*multi threads execution simple exemple*/

#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

pthread_mutex_t condition_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_cond = PTHREAD_COND_INITIALIZER;

void *funz1(void *x)
{
 printf("1) Starting 1st Thread...\n");
 sleep(1);
 /*aquisisce il lock*/
 pthread_mutex_lock(&condition_mutex);
 printf("3) 1st Thread waits 2nd Thread completes his execution...\n");
 sleep(1);
 /*aspetta l'esecuzione di un altro thread*/
 pthread_cond_wait(&condition_cond, &condition_mutex);
 sleep(1);
 pthread_mutex_unlock(&condition_mutex);
 printf("5) 1st Thread completes his execution...\n\n");

 return 0;
}


void *funz2(void *x)
{
 printf("2) Starting 2nd Thread...\n");
 sleep(1);
 /*aquisisce il lock*/
 pthread_mutex_lock(&condition_mutex);
 sleep(1);
 /*riceve il segnale di precendenza per l'esecuzione*/
 pthread_cond_signal(&condition_cond);
 sleep(1);
 pthread_mutex_unlock(&condition_mutex);
 printf("4) 2nd Thread executed...\n");

 return 0;
}

int main()
{
 pthread_t t1, t2;

 printf("\n**Starting execution of threads**\n\n");

 if(pthread_create(&t1, NULL , funz1, NULL) != 0)
 { 
  printf("Error generating threads\n");
  return 1;
 }

 if(pthread_create(&t2, NULL , funz2, NULL) != 0)
 { 
  printf("Error generating threads\n");
  return 1;
 }

 pthread_join(t1, NULL);
 pthread_join(t2, NULL);

 return 0;
}
Premetto che non ho passato molto tempo sull'argomento per via di altri impegni, pero oggi ho potuto verificare ciò:
Su una ubuntu il risultato è quello "voluto"; ossia 1, 2, 3, 4, 5 in ordine..
Sulla mia slack 12.2 invece ci sono problemi: dopo il 4 si blocca, in uno sleep senza limite di tempo..

Codice: Seleziona tutto

**Starting execution of threads**

1) Starting 1st Thread...
2) Starting 2nd Thread...
3) 1st Thread waits 2nd Thread completes his execution...
4) 2nd Thread executed...
^C
simo@localhost:
Se tolgo gli sleep dal codice il risultato è il seguente:

Codice: Seleziona tutto

**Starting execution of threads**

1) Starting 1st Thread...
3) 1st Thread waits 2nd Thread completes his execution...
2) Starting 2nd Thread...
5) 1st Thread completes his execution...

4) 2nd Thread executed...
Da cosa può essere dato il problema? Uso il kernel di default, non ho toccato la selezione nel file lilo.conf pero non capisco da cosa può nascere il problema. Qualcuno mi sa aiutare o dare qualche indicazione?
Grazie a tutti!

Re: Pthread - correttezza codice

Inviato: gio 15 apr 2010, 8:28
da Ansa89
Non ho perso molto tempo a guardare il codice (è mattina presto), ma l'ordine differente di esecuzione è probabilmente dovuto al differente algoritmo di cpu-scheduling che viene usato da ubuntu e slack.

Il perché si blocchi se nel primo caso non lo so :? .

Re: Pthread - correttezza codice

Inviato: gio 15 apr 2010, 11:27
da Luke88
Succede:
-funz1:printf (1)
-funz2:printf (2), mutex_lock, signal, mutex_unlock
-funz1:mutex_lock, printf (3), condition_wait
-funz2:printf(4)

e ovviamente, deadlock, in quanto funz1 aspetta il segnale che non arriverà mai.

datti una letta al kernighan comunque, nelle funzioni void non va messo il return e le tue funzioni prendono un argomento che non gli viene passato...
se ti va poi datti una letta allo stile di programmazione linux ( /usr/src/linux/Documentation/CodingStyle ), il migliore (imho) per programmare in C.

nel secondo caso invece:
-funz1: printf(1), mutex_lock, printf(3), condition_wait
-funz2: printf(2), mutex_lock, signal, mutex_unlock
-funz1: mutex_unlock, printf(5)
-funz2: printf(4)

l'utilità dei thread è proprio quella: le istruzioni possono venire eseguite in parallelo (più o meno), ma in qualsiasi ordine.

Re: Pthread - correttezza codice

Inviato: gio 15 apr 2010, 15:40
da mr.simo
datti una letta al kernighan comunque, nelle funzioni void non va messo il return e le tue funzioni prendono un argomento che non gli viene passato...
se ti va poi datti una letta allo stile di programmazione linux ( /usr/src/linux/Documentation/CodingStyle ), il migliore (imho) per programmare in C.
Grazie per la tua risposta.. :lol: Ho letto kernigham e libri molto piu impegnativi, pero essendo umani gli errori li possiamo fare tutti, anche se in effetti i return ai void era meglio correggerli, da dire che se non me li segnalava :-k . Distrazione mia e altri fattori... Grazie per ricordarmelo :thumbright: :D

Fatto stà che ho risolto.. L'errore come mi ha fatto notare Luke88 era alla riga nº 25 dove appunto pthread_mutex_unlock(&condition_mutex) causava un deadlock.. Ora il codice funziona come voluto. Grazie per avermi fatto notare questo dettaglio. comunque tornerò personalmente sull'argomento.. :D
Dunque il codice rimane il seguente:

Codice: Seleziona tutto

/*multi threads execution simple exemple*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t condition_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_cond = PTHREAD_COND_INITIALIZER;

void *funz1(void *x)
{
  printf("1) Starting 1st Thread...\n");
  /*aquisisce il lock*/
  pthread_mutex_lock(&condition_mutex);
  sleep(1);
  printf("3) 1st Thread waits 2nd Thread completes his execution...\n");
  sleep(1);
  /*aspetta l'esecuzione di un altro thread*/
  pthread_cond_wait(&condition_cond, &condition_mutex);
  sleep(1);
  /*pthread_mutex_unlock(&condition_mutex); ERRORE*/;
  printf("5) 1st Thread completes his execution...\n\n");
}


void *funz2(void *x)
{
  printf("2) Starting 2nd Thread...\n");
  /*aquisisce il lock*/
  pthread_mutex_lock(&condition_mutex);
  sleep(1);
  /*riceve il segnale di precendenza per l'esecuzione*/
  pthread_cond_signal(&condition_cond);
  sleep(1);
  pthread_mutex_unlock(&condition_mutex);
  printf("4) 2nd Thread executed...\n");
}

int main()
{
  pthread_t t1, t2;
  printf("\n**Starting execution of threads**\n\n");

  if(pthread_create(&t1, NULL , funz1, NULL) != 0)
  { 
    printf("Error generating threads\n");
    return 1;
  }

  if(pthread_create(&t2, NULL , funz2, NULL) != 0)
  { 
    printf("Error generating threads\n");
    return 1;
  }

  pthread_join(t1, NULL);
  pthread_join(t2, NULL);
  return 0;
}
Ciao grazie mille!!!

Re: [SOLVED] Pthread - correttezza codice

Inviato: gio 15 apr 2010, 17:47
da Luke88
uh... no.

per cominciare, le tue due funzioni non ritornano void, ma puntatori a void, quindi stai ancora sbagliando la dichiarazione.
poi le tue funzioni prendono ancora un argomento, anche se non glielo passi.

metti quelle funzioni a void, togli gli argomenti e fai partire i thread con casting a puntatore a void dell'indirizzo della funzione.

comunque può ancora andare in deadlock.
esempio:

-funz2:printf(2), mutex_lock, signal, mutex_unlock, printf(4)
-funz1:printf(1), mutex_lock, printf(3), condition_wait

deadlock, sta in attesa del segnale che non arriverà mai.

inoltre, direttamente dal man di pthread_cond_wait:
man ha scritto: These functions atomically release mutex and cause the calling thread to block on the condition variable cond;

Upon successful return, the mutex shall have been locked and shall be owned by the calling thread.
ergo la cond_wait prima rilascia la mutex, sta in attesa del segnale, e appena riceve il segnale riblocca la mutex, e esce.

funz1 non rilascia la mutex. termina (a volte), ma la mutex è sempre bloccata.

Re: [SOLVED] Pthread - correttezza codice

Inviato: gio 15 apr 2010, 19:03
da mr.simo
per cominciare, le tue due funzioni non ritornano void, ma puntatori a void, quindi stai ancora sbagliando la dichiarazione.
poi le tue funzioni prendono ancora un argomento, anche se non glielo passi.
Si per gli argomenti hai ragione li creai inutilmente.. Altra stupidaggine.
pthread_create prende comunque come 3º argomento un puntatore a void.. Per questo feci cosi.. App arr a casa seguo il tuo consiglio. :thumbright:

EDIT: ho tolto gli argomenti inutili etc, comunque il deadlock comunque non si verifica.. Dovrebbe andare bene cosi credo.. :-k