thread synchronisation
-
hi, ich würd wieder mal eure hilfe brauchen
kann mir jemand erlären wieso der folgende code nicht funktioniert so wie ich
mir das vorstelle.es werden 10 consumer(player) threads gestartet und ein producer(master). der masterthread sendet ein pthread_broadcast an alle player. die ausgabe ist dann folgende:
player -1853483264 beginns
player -1853483264 ready
player -1861875968 beginns
player -1861875968 ready
player -1870268672 beginns
player -1870268672 ready
player -1878661376 beginns
player -1878661376 ready
player -1887054080 beginns
player -1887054080 ready
player -1895446784 beginns
player -1895446784 ready
player -1903839488 beginns
player -1903839488 ready
player -1912232192 beginns
player -1912232192 ready
player -1920624896 beginns
player -1920624896 readyEs werden also 9 der 10 threads ausgeführt. manchmal auch weniger. meine frage ist wieso nicht immer alle 10?
#include <stdio.h> #include <pthread.h> #include <stdlib.h> #define CNT_PLAYER 10 #define CNT_NUMBER 10 pthread_mutex_t mutex_player; pthread_mutex_t mutex_master; pthread_cond_t master_ready; pthread_barrier_t bar; int ready = 0; void *player(void *arg) { pthread_mutex_lock(&mutex_player); while(ready == 0) pthread_cond_wait(&master_ready,&mutex_player); printf("player %d beginns\n",(int)pthread_self()); pthread_mutex_unlock(&mutex_player); printf("player %d ready\n",(int)pthread_self()); pthread_barrier_wait(&bar); } void *master(void *arg) { pthread_mutex_lock(&mutex_master); printf("master\n"); pthread_cond_broadcast(&master_ready); pthread_mutex_unlock(&mutex_master); ready = 1; } int main(int argc, char **argv) { int i = 0; pthread_mutex_init(&mutex_master,NULL); pthread_cond_init(&master_ready,NULL); pthread_barrier_init(&bar, NULL, CNT_PLAYER); pthread_t threads[CNT_PLAYER+3]; for(i = 0;i < CNT_PLAYER; i++) { pthread_create(&threads[i],NULL,player,NULL); } pthread_create(&threads[11],NULL,master,NULL); for(i=0; i < CNT_PLAYER+1; i++) { pthread_join(threads[i], NULL); } //pthread_mutex_destroy(&mutex); }
mein gedanke ist dass das pthread_broadcast nicht bei allen threads ankommt. nur soll der master thread einen wert berechnen und den genau ein einziges mal an alle threads übergeben und diese starten.
-
Wenn pthread_cond_broadcast aufgerufen wird, kann es sein, dass noch nicht alle Threads auf ein Signal mittels pthread_cond_wait warten.
-
hmm aber ein
for(i = 0;i < CNT_PLAYER; i++) { pthread_create(&threads[i],NULL,player,NULL); } sleep(1); pthread_create(&threads[11],NULL,master,NULL);
müsste das probem dann doch lösen oder?
-
Warten loest keine Synchronisationsprobleme. Auch hier kann ich eine Situation konstruieren, bei dem nicht alle Threads abgearbeitet werden.
-
ich weiss dass das keine synchronisationsprobleme löst. aber in diesem fall müsste es dann ja funktionieren da sicher alle threads dann warten. tut es aber leider nicht also muss das problem wo anders liegen.
-
Jetzt muss ich es mir doch genau ansehen ...
pthread_cond_wait(&master_ready,&mutex_player);
Wo bitte wird mutex_player initialisiert. Btw. Normalerweise ist hier die zu synchronisierende Variable "ready". D.h. sie sollte von einem Mutex geschuetzt werden. Dieser Mutex wird sowohl von Master als auch Player benutzt.
void *master(void *arg) { pthread_mutex_lock(&mutex_master); printf("master\n"); pthread_cond_broadcast(&master_ready); pthread_mutex_unlock(&mutex_master); ready = 1; }
Bitte was soll hier durch den mutex_master geschuetzt werden?
PS: Es waere auch sinnvoll, die Rueckgabewerte die Threadfunktionen zu pruefen. Gerade wenn unklar ist, warum es nicht funktioniert.
-
sry ich wollt den code übersichtlicher halten und hab nur das wichtigste gepostet.initialisierung hab ich wohl aus versehen gelöscht. mutex_master wird natürlich in der main initialisiert.
Bitte was soll hier durch den mutex_master geschuetzt werden?
void *master(void *arg) { pthread_mutex_lock(&mutex_master); printf("master\n"); printf("berechnung...\n"); pthread_cond_broadcast(&master_ready); ready = 1; pthread_mutex_unlock(&mutex_master); }
Hier sollte einfach irgendetwas berechnet werden.
Ok wenn ich das richtig verstanden habe muss ich für den master und player
den selben mutex verwenden? dachte ich kann das auch mit 2 verschiedenen lösen
deswegen auch mutex_master und mutex_player?
-
Nein, wenn du den Zugriff auf "ready" synchronisieren moechtest, muessen alle beteiligten den Mutex fuer "ready" verwenden.
-
xxmaxx schrieb:
ich weiss dass das keine synchronisationsprobleme löst. aber in diesem fall müsste es dann ja funktionieren da sicher alle threads dann warten. tut es aber leider nicht also muss das problem wo anders liegen.
Dann versuche nicht, Syncronisationsprobleme mit Warten zu lösen. Warten ist praktisch immer falsch.
Übrigens ist "beginns" lustig. Entweder Deutsch "beginn" oder englisch "begins".
-
sry ich wollt den code übersichtlicher halten und hab nur das wichtigste gepostet.initialisierung hab ich wohl aus versehen gelöscht. mutex_master wird natürlich in der main initialisiert.
1.) Zeige ein minimal kompilierbares Beispiel, bei dem der Fehler auftritt!
2.) Ich habe von mutex_player gesprochen, nicht von mutex_master.
-
Zeige ein minimal kompilierbares Beispiel, bei dem der Fehler auftritt!
bei dem beispiel tritt der fehler ja auf:
#include <stdio.h> #include <pthread.h> #include <stdlib.h> #define CNT_PLAYER 10 #define CNT_NUMBER 10 pthread_mutex_t mutex_player; pthread_mutex_t mutex_master; pthread_cond_t master_ready; int ready = 0; void *player(void *arg) { pthread_mutex_lock(&mutex_player); while(ready == 0) { pthread_cond_wait(&master_ready,&mutex_player); } printf("player %d begins\n",(int)pthread_self()); pthread_mutex_unlock(&mutex_player); printf("player %d ready\n",(int)pthread_self()); } void *master(void *arg) { pthread_mutex_lock(&mutex_master); printf("master\n"); pthread_cond_broadcast(&master_ready); ready = 1; pthread_mutex_unlock(&mutex_master); } int main(int argc, char **argv) { int i = 0; pthread_mutex_init(&mutex_master,NULL); pthread_mutex_init(&mutex_player,NULL); pthread_cond_init(&master_ready,NULL); pthread_t threads[CNT_PLAYER+1]; for(i = 0;i < CNT_PLAYER; i++) { pthread_create(&threads[i],NULL,player,NULL); } pthread_create(&threads[10],NULL,master,NULL); for(i=0; i < CNT_PLAYER+1; i++) { pthread_join(threads[i], NULL); } //pthread_mutex_destroy(&mutex); }
ich möchte einfach dass der master ein signal gibt und alle anderen player threads starten und zum schluss jeder player ready ausgibt. wie gesagt
wird das nur 9 mal ausgegeben. wie soll ich sonst die beiden threads synchronisieren?
-
Du verwendest immernoch zwei unterschiedliche Mutexe fuer
ready
.
-
ok stimmt. jetzt funktionierts auch. danke