Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3295 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Threads Posix et verrous

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Threads Posix et verrous

n°1495063
HomerJK
Posté le 21-12-2006 à 21:32:37  profilanswer
 

Bonjour  :hello:  
 
Je cherche à savoir utiliser les verrous qui fonctionnent avec les pthreads.
Ainsi, j'ai fait un petit programme qui permet à deux pthreads de pouvoir incrémenter successivement puis afficher une variable.
Seulement voilà, le programme n'affiche rien. En fait, je pense que le programme ne cree par les pthread correctement.
Merci d'avance de pouvoir m'aider.
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. typedef struct{
  5. pthread_mutex_t * verrou;
  6. char * message;
  7. int * ressource;
  8. } vermess;
  9. void * routine (vermess * V)
  10. {
  11. int i;
  12. for(i=0;i<10;i++)
  13. {
  14.  pthread_mutex_lock (V->verrou);
  15.  V->ressource++;
  16.  printf("%s %d\n",V->message,V->ressource);
  17.  pthread_mutex_unlock (V->verrou);
  18. }
  19.     pthread_exit (0);
  20. }
  21. int main()
  22. {
  23. int erreur1,erreur2, argument = 3;
  24. int ressource=0;
  25.     pthread_t p1,p2;
  26. pthread_mutex_t verrou;
  27. pthread_mutex_init(&verrou, NULL);
  28. vermess * V1=(vermess *)malloc(sizeof(vermess));
  29. V1->verrou=&verrou;
  30. V1->ressource=&ressource;
  31. V1->message="Je suis le thread 1 : ";
  32. vermess * V2=(vermess *)malloc(sizeof(vermess));
  33. V2->verrou=&verrou;
  34. V2->ressource=&ressource;
  35. V2->message="Je suis le thread 2 :     ";
  36.     erreur1 = pthread_create (&p1, NULL, routine, V1);
  37. erreur2 = pthread_create (&p2, NULL, routine, V2);
  38.     if (erreur1 != 0) fprintf(stderr,"Echec creation de thread: %d\n",erreur1);
  39.  if (erreur2 != 0) fprintf(stderr,"Echec creation de thread: %d\n",erreur2);
  40. return 0;
  41. }


 
La structure vermess (pour Verrou-Message) permet de faire passer deux arguments dans la fonction routine.

mood
Publicité
Posté le 21-12-2006 à 21:32:37  profilanswer
 

n°1495074
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 22:00:30  profilanswer
 

Bien que je ne connaisse pas les pthreads (donc important disclaimer), ton code a l'air pas mal. Par contre, la doc de pthread_mutex_lock me dit que l'aquisition du lock n'est pas réentrante (ce qui n'est pas étonnant de la part de Xavier Leroy), donc le risque de deadlock est important.
Que se passe-t'il si tu remplaces l'appel par pthread_mutex_trylock, ou que tu changes le type du mutex en PTHREAD_MUTEX_RECURSIVE ou PTHREAD_MUTEX_ERRORCHECK ?
De façon générale, pour un usage standard (où les perfs maximales ne sont pas absolument cruciales), je privilégierais plutôt le trylock sur le lock de base.

Message cité 1 fois
Message édité par el muchacho le 21-12-2006 à 22:02:43
n°1495075
farib
Posté le 21-12-2006 à 22:01:20  profilanswer
 

Déja, par principe, met des pthread_join, des fois que..


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495076
farib
Posté le 21-12-2006 à 22:03:13  profilanswer
 

el muchacho a écrit :

Bien que je ne connaisse pas les pthreads (donc important disclaimer), ton code a l'air pas mal. Par contre, la doc de pthread_mutex_lock me dit que l'aquisition du lock n'est pas réentrante (ce qui n'est pas étonnant de la part de Xavier Leroy), donc le risque de deadlock est important.  
?


Euh, si les mutex sont pas réentrants, on risque pas d'être mal barrés pour les utiliser ?


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495077
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 22:04:21  profilanswer
 

farib a écrit :

Euh, si les mutex sont pas réentrants, on risque pas d'être mal barrés pour les utiliser ?


Ben si:
"If the mutex type is PTHREAD_MUTEX_NORMAL, deadlock detection is not provided. Attempting to relock the mutex causes deadlock. If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, undefined behaviour results.
(...)
If the mutex type is PTHREAD_MUTEX_DEFAULT, attempting to recursively lock the mutex results in undefined behaviour. Attempting to unlock the mutex if it was not locked by the calling thread results in undefined behaviour. Attempting to unlock the mutex if it is not locked results in undefined behaviour."

 

C'est chaud à utiliser.


Message édité par el muchacho le 21-12-2006 à 22:07:25
n°1495079
farib
Posté le 21-12-2006 à 22:12:20  profilanswer
 

bah ça c si tu fais deux locks comme un con [:spamafote]
si t'enchaines  

Code :
  1. pthread_lock(mutex1);
  2. pthread_mutex_lock(mutex2);


forcément t mal barré !
 
en l'occurrence son pb se règle en mettant des pthread_join
 
en fait, sans, le thread principal meurt et emmene avec lui son stdout, un strace donne:
 

sendto(-1210598640, umovestr: Input/output error


 
y'a un 2e bug, c V->ressour++
 
tu incémentes un pointeur, erreur


Message édité par farib le 21-12-2006 à 22:14:32

---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495081
HomerJK
Posté le 21-12-2006 à 22:13:57  profilanswer
 

Merci pour vos réponses !
En fait j'ai rajouté les pthread_join() et du coup ca marche.
Seulement ca ne fonctionne pas comme je le veux :  
 
Je suis le thread 1 :  4
Je suis le thread 1 :  8
Je suis le thread 1 :  12
Je suis le thread 1 :  16
Je suis le thread 1 :  20
Je suis le thread 1 :  24
Je suis le thread 1 :  28
Je suis le thread 1 :  32
Je suis le thread 1 :  36
Je suis le thread 1 :  40
Je suis le thread 2 :      4
Je suis le thread 2 :      8
Je suis le thread 2 :      12
Je suis le thread 2 :      16
Je suis le thread 2 :      20
Je suis le thread 2 :      24
Je suis le thread 2 :      28
Je suis le thread 2 :      32
Je suis le thread 2 :      36
Je suis le thread 2 :      40
 
Voilà ce qu'il m'affiche.
Là il est clair que les verrous n'ont pas l'air de fonctionner.
Seulement voilà si vous pouviez encore m'aider pour resoudre ce problème car je ne vois pas la solution...
 
edit - en effet, j'ai modifié entretemps le probleme pour l'acces a la ressource


Message édité par HomerJK le 21-12-2006 à 22:15:19
n°1495082
farib
Posté le 21-12-2006 à 22:14:57  profilanswer
 

pointeur cf remarque du dessus

 

edit spassa
edit2 touvabien


Message édité par farib le 21-12-2006 à 22:19:23

---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495085
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 22:20:20  profilanswer
 

farib> Pas forcément: ici, je ne vois pas ce qui empêche de tomber dans le cas où p1 locke le verrou et p2 tente de le délocker.

Message cité 1 fois
Message édité par el muchacho le 21-12-2006 à 22:21:34
n°1495087
farib
Posté le 21-12-2006 à 22:21:36  profilanswer
 

el muchacho a écrit :

Pas forcément: ici, je ne vois pas ce qui empêche de tomber dans le cas où p1 locke le verrou et p2 tente de le délocker.


 
oui oui,  
 
le deadlock est avant tout une erreur de conception du programme et d'utilisation des threads, alors c réglé :o


---------------
Bitcoin, Magical Thinking, and Political Ideology
mood
Publicité
Posté le 21-12-2006 à 22:21:36  profilanswer
 

n°1495088
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 22:24:33  profilanswer
 

Et je pense que c'est ce qui se passe. [:spamafote]
Il serait intéressant de voir ce que ça donne avec trylock.
Et pthread_join, finalement, ça sérialise les 2 threads  (ce qu'on voit dans sa sortie), si je comprends bien, puisqu'on attend la mort de p1 ?

Message cité 1 fois
Message édité par el muchacho le 21-12-2006 à 22:25:46
n°1495092
HomerJK
Posté le 21-12-2006 à 22:28:12  profilanswer
 

Quand je fais V->ressource++; j'incrémente le pointeur mais pas la valeur du pointeur ? Une solution ?

n°1495093
farib
Posté le 21-12-2006 à 22:28:19  profilanswer
 

el muchacho a écrit :

Et je pense que c'est ce qui se passe. [:spamafote]
Il serait intéressant de voir ce que ça donne avec trylock.
Et pthread_join, finalement, ça sérialise les 2 threads  (ce qu'on voit dans sa sortie), si je comprends bien, puisqu'on attend la mort de p1 ?


 
nan  
 
pthread_join empeche juste le thread main() de crever avant que les threads ne s'exécutent
 
apres au niveau des mutexes, il n'y a pas de garanties quand au réveil des threads, au niveau du scheduler, etc...
 
dans le cas présent, comme c'est simple, il a le temps de faire tout le premier thread avant que le scheduler linux (ou autre) bascule vers l'autre thread

Message cité 1 fois
Message édité par farib le 21-12-2006 à 22:30:01

---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495094
farib
Posté le 21-12-2006 à 22:29:39  profilanswer
 

HomerJK a écrit :

Quand je fais V->ressource++; j'incrémente le pointeur mais pas la valeur du pointeur ? Une solution ?


(*(V->ressource))++;
 
 
je blinde de parentheses parce que je suis aps sur des priorités des opérateurs


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495096
HomerJK
Posté le 21-12-2006 à 22:30:56  profilanswer
 

J'ai essayé avec trylock mais ca n'a pas changé le résultat d'affichage :

Code :
  1. void * routine (vermess * V)
  2. {
  3. int i, test;
  4. for(i=0;i<10;i++)
  5. {
  6.  do
  7.  {
  8.  test=pthread_mutex_trylock (V->verrou);
  9.  }while(test!=0);
  10.  V->ressource++;
  11.  printf("%s %d\n",V->message,V->ressource);
  12.  pthread_mutex_unlock (V->verrou);
  13. }
  14.     pthread_exit (0);
  15. }

n°1495099
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 22:31:19  profilanswer
 

farib a écrit :


dans le cas présent, comme c'est simple, il a le temps de faire tout le premier thread avant que le scheduler linux (ou autre) bascule vers l'autre thread


Ah ok, c'est bien possible, en effet (malgré les printf).

n°1495100
farib
Posté le 21-12-2006 à 22:31:59  profilanswer
 

t'as modifié quoi ?
 
avec les join, les modifs sur ressource (le pointeur comme je l'ai donnée, et aussi le printf)


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495101
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 22:32:23  profilanswer
 

HomerJK a écrit :

J'ai essayé avec trylock mais ca n'a pas changé le résultat d'affichage :

Code :
  1. void * routine (vermess * V)
  2. {
  3. int i, test;
  4. for(i=0;i<10;i++)
  5. {
  6.  do
  7.  {
  8.  test=pthread_mutex_trylock (V->verrou);
  9.  }while(test!=0);
  10.  V->ressource++;
  11.  printf("%s %d\n",V->message,V->ressource);
  12.  pthread_mutex_unlock (V->verrou);
  13. }
  14.     pthread_exit (0);
  15. }



Même en enlevant le pthread_join et en augmentant le nbre d'itérations de la boucle à 10000?
 
edit: lis la doc: il faut décrémenter autant de fois le lock count qu'il a été incrémenté, sinon le lock n'est pas libéré.


Message édité par el muchacho le 21-12-2006 à 22:37:39
n°1495102
farib
Posté le 21-12-2006 à 22:32:47  profilanswer
 

el muchacho a écrit :

Ah ok, c'est bien possible, en effet (malgré les printf).


c'est juste sûr [:spamafote]


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495104
farib
Posté le 21-12-2006 à 22:35:44  profilanswer
 

Faudrait rajouter des usleep() a base de random pour forcer le mutex à travailler


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495107
HomerJK
Posté le 21-12-2006 à 22:39:15  profilanswer
 

arf, je m'y retrouve plus :)
en fait (*(V->ressource))++;  ne fonctionne pas il me met une erreur de segmentation.
Sinon je ne peux pas enlever les pthread_join sinon ca ne marche pas.
Je vais essayer vos autres méthodes.
Merci encore pour les réponses.

n°1495108
farib
Posté le 21-12-2006 à 22:41:10  profilanswer
 

chezmoi ça marche [:spamafote]


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495110
farib
Posté le 21-12-2006 à 22:41:47  profilanswer
 

HomerJK a écrit :

arf, je m'y retrouve plus :)
en fait (*(V->ressource))++;  ne fonctionne pas il me met une erreur de segmentation.
Sinon je ne peux pas enlever les pthread_join sinon ca ne marche pas.
Je vais essayer vos autres méthodes.
Merci encore pour les réponses.


 
t'as modifié quoi concernant les pointeurs ?


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495113
HomerJK
Posté le 21-12-2006 à 22:45:03  profilanswer
 

En fait pas grand-chose, je vais reassayer tout ca demain, je dois vraiment m'en aller désolé...
Je vous remercie encore pour votre aide.
@demain

n°1495115
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 22:49:40  profilanswer
 

Euh, j'ai pas de compilo sous la main pour tester mais à vue de nez j'aurais dit que V->ressource++, c'est correct et par contre l'initialisation, c'est  V->ressource= ressource (et non &ressource).
Mais ta correction farib devrait marcher aussi.

Message cité 1 fois
Message édité par el muchacho le 21-12-2006 à 22:52:06
n°1495119
farib
Posté le 21-12-2006 à 23:03:28  profilanswer
 

el muchacho a écrit :

Euh, j'ai pas de compilo sous la main pour tester mais à vue de nez j'aurais dit que V->ressource++, c'est correct et par contre l'initialisation, c'est  V->ressource= ressource (et non &ressource).
Mais ta correction farib devrait marcher aussi.


 
V-> ressource est un int *


---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1495122
el muchach​o
Comfortably Numb
Posté le 21-12-2006 à 23:08:54  profilanswer
 

ah mince, c't'erreur de nOOb... [:arn0]


Message édité par el muchacho le 21-12-2006 à 23:10:03
n°1495139
Emmanuel D​elahaye
C is a sharp tool
Posté le 21-12-2006 à 23:30:40  profilanswer
 

HomerJK a écrit :

Je cherche à savoir utiliser les verrous qui fonctionnent avec les pthreads.
Ainsi, j'ai fait un petit programme qui permet à deux pthreads de pouvoir incrémenter successivement puis afficher une variable.


http://mapage.noos.fr/emdel/pthreads.htm


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1495458
HomerJK
Posté le 22-12-2006 à 19:30:04  profilanswer
 

Re-bonjour
Pour le probleme d'incrementation j'ai reglé mon probleme, je suis passé par une valeur intermédiaire. :  

Code :
  1. int temp=(int) V->ressource;
  2. temp++;
  3. V->ressource=(int *) temp;


Sinon sur la page dont emmanuel Delahaye m'a filé le lien, j'ai fait un copier/coller d'un programme de synchronisation de verrous qui fonctionnait sans probleme, puis je l'ai exécuté sur le mien : le resultat est exactement le meme que celui de mon programme.
Je ne comprends pas...
Sinon j'ai rajouté un sleep(1) sur mon programme :

Code :
  1. void * routine (vermess * V)
  2. {
  3. int i, test;
  4. for(i=0;i<10;i++)
  5. {
  6.  do
  7.  {
  8.  test=pthread_mutex_trylock (V->verrou);
  9.  }while(test!=0);
  10.  int temp=(int) V->ressource;
  11.  temp++;
  12.  V->ressource=(int *) temp;
  13.  printf("%s %d\n",V->message,V->ressource);
  14.  do
  15.  {
  16.  test=pthread_mutex_unlock (V->verrou);
  17.  }while(test!=0);
  18.  sleep(1);
  19. }
  20.     pthread_exit (0);
  21. }


 Et voici l'affichage :  
Je suis le thread 1 :  1
Je suis le thread 2 :      1
Je suis le thread 1 :  2
Je suis le thread 2 :      2
Je suis le thread 1 :  3
Je suis le thread 2 :      3
Je suis le thread 1 :  4
Je suis le thread 2 :      4
Je suis le thread 1 :  5
Je suis le thread 2 :      5
Je suis le thread 1 :  6
Je suis le thread 2 :      6
Je suis le thread 1 :  7
Je suis le thread 2 :      7
Je suis le thread 1 :  8
Je suis le thread 2 :      8
Je suis le thread 1 :  9
Je suis le thread 2 :      9
Je suis le thread 1 :  10
Je suis le thread 2 :      10
 
Lors de l'affichage, le sleep(1) ne prend effet que tous les deux messages (apres "je suis le thread 2" ), de même que l'incrémentation de la variable ressource.
Or, au bout du compte, ressource devrait atteindre la valeur 20, et non 10 comme ici.

Message cité 1 fois
Message édité par HomerJK le 22-12-2006 à 19:30:58
n°1495468
Emmanuel D​elahaye
C is a sharp tool
Posté le 22-12-2006 à 19:53:25  profilanswer
 

HomerJK a écrit :

Re-bonjour
Pour le probleme d'incrementation j'ai reglé mon probleme, je suis passé par une valeur intermédiaire. :

Code :
  1. int temp=(int) V->ressource;
  2. temp++;
  3. V->ressource=(int *) temp;




Tu cherches à incrémenter quoi ? Le pointeur ou la valeur pointée ?

 

Si c'est le pointeur :

Code :
  1. V->ressource++;


Si c'est la valeur pointée :

Code :
  1. (*V->ressource)++;



Message édité par Emmanuel Delahaye le 22-12-2006 à 20:45:24

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1495475
HomerJK
Posté le 22-12-2006 à 20:03:40  profilanswer
 

Je cherchais à incrémenter la valeur, mais j'ai réglé mon probleme.
Sinon ta méthode d'incrémentation de la valeur pointée (*V->ressource)++; provoque une erreur de segmentation.

n°1495491
Emmanuel D​elahaye
C is a sharp tool
Posté le 22-12-2006 à 20:51:26  profilanswer
 

HomerJK a écrit :

Je cherchais à incrémenter la valeur, mais j'ai réglé mon probleme.
Sinon ta méthode d'incrémentation de la valeur pointée (*V->ressource)++; provoque une erreur de segmentation.


Curieux. Tu es sûr que le pointeur est correct ?
 

Code :
  1. #include <stdio.h>
  2. struct data
  3. {
  4.    int *pi;
  5. };
  6. static void prt_i (struct data const *p_data)
  7. {
  8.    printf ("i=%d\n", *p_data->pi);
  9. }
  10. static void inc_i (struct data *p_data)
  11. {
  12.    (*p_data->pi)++;
  13. }
  14. int main (void)
  15. {
  16.    int i = 0;
  17.    struct data data = { &i };
  18.    prt_i (&data);
  19.    inc_i (&data);
  20.    prt_i (&data);
  21.    return 0;
  22. }



i=0
i=1
 
Press ENTER to continue.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1495499
HomerJK
Posté le 22-12-2006 à 21:10:45  profilanswer
 

C'est bon j'ai réglé mon probleme.
En fait c'était une mauvaise manipulation du pointeur : chaque thread accédait à leur propre variable ressource.
Maintenant, c'est bon, ils ont en commun une seule variable ressource.
Du coup, l'instruction (*V->ressource)++; marche.
 
Voila ce que ca m'affiche maintenant :  
Je suis le thread 1 :  1
Je suis le thread 2 :      2
Je suis le thread 1 :  3
Je suis le thread 2 :      4
Je suis le thread 1 :  5
Je suis le thread 2 :      6
Je suis le thread 1 :  7
Je suis le thread 2 :      8
Je suis le thread 1 :  9
Je suis le thread 2 :      10
Je suis le thread 1 :  11
Je suis le thread 2 :      12
Je suis le thread 1 :  13
Je suis le thread 2 :      14
Je suis le thread 1 :  15
Je suis le thread 2 :      16
Je suis le thread 1 :  17
Je suis le thread 2 :      18
Je suis le thread 1 :  19
Je suis le thread 2 :      20
 
Seulement cela fonctionne qu'avec l'intruction sleep(1); Il est possible de faire en sorte que cela fonctionne sans ?

n°1495502
Emmanuel D​elahaye
C is a sharp tool
Posté le 22-12-2006 à 21:31:16  profilanswer
 

HomerJK a écrit :

Seulement cela fonctionne qu'avec l'intruction sleep(1); Il est possible de faire en sorte que cela fonctionne sans ?


Si il y a un mécanisme de synchronisation, oui, ce sera selon le bon vouloir du système. De toutes façons, une tache que ne rend pas la main, c'est crade. Un système un peu malin pourrait très bien la punir en augmentant son ratio de temps, voir en la supprimant carrément...
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1495660
Taz
bisounours-codeur
Posté le 23-12-2006 à 14:41:36  profilanswer
 

Comment ça ne fonctionne qu'avec sleep ?

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Threads Posix et verrous

 

Sujets relatifs
Simulation de threads en javascriptLister les threads en C
Fork() et threadsWin32, threads, messages et blocages
liste des flags de POSIXProbleme de synchronisation ecriture tubes / multi threads fork
THREADS - utilisation de pthread.hProblèmes de variables communes à différents Threads
Threads sur un serveur J2EE ? Thread en tant que Singleton?Cherche docs/info sur threads
Plus de sujets relatifs à : Threads Posix et verrous


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR