Threads Posix et verrous - C - Programmation
Marsh Posté le 21-12-2006 à 22:00:30
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.
Marsh Posté le 21-12-2006 à 22:01:20
Déja, par principe, met des pthread_join, des fois que..
Marsh Posté le 21-12-2006 à 22:03:13
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 ?
Marsh Posté le 21-12-2006 à 22:04:21
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.
Marsh Posté le 21-12-2006 à 22:12:20
bah ça c si tu fais deux locks comme un con
si t'enchaines
Code :
|
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
Marsh Posté le 21-12-2006 à 22:13:57
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
Marsh Posté le 21-12-2006 à 22:14:57
pointeur cf remarque du dessus
edit spassa
edit2 touvabien
Marsh Posté le 21-12-2006 à 22:20:20
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.
Marsh Posté le 21-12-2006 à 22:21:36
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é
Marsh Posté le 21-12-2006 à 22:24:33
Et je pense que c'est ce qui se passe.
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 ?
Marsh Posté le 21-12-2006 à 22:28:12
Quand je fais V->ressource++; j'incrémente le pointeur mais pas la valeur du pointeur ? Une solution ?
Marsh Posté le 21-12-2006 à 22:28:19
el muchacho a écrit : Et je pense que c'est ce qui se passe. |
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
Marsh Posté le 21-12-2006 à 22:29:39
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
Marsh Posté le 21-12-2006 à 22:30:56
J'ai essayé avec trylock mais ca n'a pas changé le résultat d'affichage :
Code :
|
Marsh Posté le 21-12-2006 à 22:31:19
farib a écrit : |
Ah ok, c'est bien possible, en effet (malgré les printf).
Marsh Posté le 21-12-2006 à 22:31:59
t'as modifié quoi ?
avec les join, les modifs sur ressource (le pointeur comme je l'ai donnée, et aussi le printf)
Marsh Posté le 21-12-2006 à 22:32:23
HomerJK a écrit : J'ai essayé avec trylock mais ca n'a pas changé le résultat d'affichage :
|
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é.
Marsh Posté le 21-12-2006 à 22:32:47
el muchacho a écrit : Ah ok, c'est bien possible, en effet (malgré les printf). |
c'est juste sûr
Marsh Posté le 21-12-2006 à 22:35:44
Faudrait rajouter des usleep() a base de random pour forcer le mutex à travailler
Marsh Posté le 21-12-2006 à 22:39:15
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.
Marsh Posté le 21-12-2006 à 22:41:10
ReplyMarsh Posté le 21-12-2006 à 22:41:47
HomerJK a écrit : arf, je m'y retrouve plus |
t'as modifié quoi concernant les pointeurs ?
Marsh Posté le 21-12-2006 à 22:45:03
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
Marsh Posté le 21-12-2006 à 22:49:40
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.
Marsh Posté le 21-12-2006 à 23:03:28
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). |
V-> ressource est un int *
Marsh Posté le 21-12-2006 à 23:08:54
ah mince, c't'erreur de nOOb...
Marsh Posté le 21-12-2006 à 23:30:40
HomerJK a écrit : Je cherche à savoir utiliser les verrous qui fonctionnent avec les pthreads. |
http://mapage.noos.fr/emdel/pthreads.htm
Marsh Posté le 22-12-2006 à 19:30:04
Re-bonjour
Pour le probleme d'incrementation j'ai reglé mon probleme, je suis passé par une valeur intermédiaire. :
Code :
|
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 :
|
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.
Marsh Posté le 22-12-2006 à 19:53:25
HomerJK a écrit : Re-bonjour
|
Tu cherches à incrémenter quoi ? Le pointeur ou la valeur pointée ?
Si c'est le pointeur :
Code :
|
Si c'est la valeur pointée :
Code :
|
Marsh Posté le 22-12-2006 à 20:03:40
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.
Marsh Posté le 22-12-2006 à 20:51:26
HomerJK a écrit : Je cherchais à incrémenter la valeur, mais j'ai réglé mon probleme. |
Curieux. Tu es sûr que le pointeur est correct ?
Code :
|
|
Marsh Posté le 22-12-2006 à 21:10:45
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 ?
Marsh Posté le 22-12-2006 à 21:31:16
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...
Marsh Posté le 21-12-2006 à 21:32:37
Bonjour
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.
La structure vermess (pour Verrou-Message) permet de faire passer deux arguments dans la fonction routine.