POSIX Threads condition synchronisation
-
Hallo Wissende dieser Programmierer-welt!
Ich habe ein Problem mit der Synchronisation von threads via conditions. Es scheint, als würden conditions nicht immer zugestellt zu werden!
Folgende Situation:
Thread 1, Thread 2 starten ( pthread_create() )
Thread 1 macht einen INET socket auf und wartet auf eingehende Pakete.
Thread 2 initialisiert eine API und wartet dann per pthread_cond_timedwait auf eine condition von Thread 1.
Thread 1 schickt immer eine condition (pthread_cond_signal()) wenn eingehende daten zur weiterbearbeitung anstehen.Soweit alles toll und gut. Wenn jedoch Thread 1 sofort ein paket bekommt und Thread 2 noch in der initialisierung der API steckt geht das Signal aus pthread_cond_signal() verloren!
Ich dachte das das zustellen der conditions verlässlich ist oder hab ich da was vergessen?Daaanke für die Hilfe!
Karschie
-
dann brauchst du irgendwo ein flag, das der thread2 erst setzt, wenn er fertig ist.
dann darfst du conditions senden.
musst halt mal gucken, wie die beiden da auf den gleichen speicher zugreifen können.
-
Hallo Karschie,
Die Conditions von pthread verhalten sich anders, als unter Windows mit SetEvent() und WaitForSingleObject(). Die Condition bleibt, nach pthread_cond_signal() nicht Signalisiert. Daher ist man gezwungen vor dem Aufruf pthread_cond_wait(), auf vohandene "Daten" zu prüfen. Damit es bei der Prüfung nicht zu einer race-condition kommen kann, benötitgt man eine Mutex.
gruss sam
-
Moin!
Vielen Dank für eure Hilfe! Letztlich war ich etwas unklar in meiner Anfrage ( Großes Sorry dafür, Lag an zu wenig Bier und Ernüssen! )
Das problem ist whol, das eine Condition nur zugestellt wird wenn ein Thread auf diese condition wartet (pthread_cond_wait). Eine predicate variable( oder eben daten ) würden es schon richten. Ein Mutex ist ja impliziet an pthread_cond_wait gebunden.Eine predicate variable hat mir letztlich geholfen anhand derer ich fetsstellen kann obdas Signal schon gelaufen ist oder nicht.Daaanke schon Mal!
KarschieWen es interssiert ein kleines Testprogramm...
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <pthread.h> typedef struct { pthread_t thread; pthread_attr_t attr; } thrd_t; typedef struct context { int sync_predicate; // threads thrd_t com_thrd; thrd_t main_thrd; // lists, mutexes, conditions pthread_mutex_t sync_mutex; pthread_cond_t sync_cond; } lsfgw_t; static void *main_thread(void *threaddata); static void *com_thread(void *threaddata); int main(int ac , char **av) { lsfgw_t *GW = NULL; GW=(lsfgw_t *)malloc(sizeof(*GW)); memset(GW, 0, sizeof(*GW)); /* * init threads and mutexes */ pthread_attr_init(&GW->com_thrd.attr); pthread_attr_init(&GW->main_thrd.attr); pthread_mutex_init(&GW->sync_mutex, NULL); pthread_cond_init(&GW->sync_cond, NULL); // make shure every thread is locked! pthread_mutex_lock(&GW->sync_mutex); /* * create threads */ if(pthread_create( &GW->com_thrd.thread, &GW->com_thrd.attr, com_thread, GW)) { fprintf(stderr,"Cant create com thread <%s>\n",strerror(errno)); exit(-1); } if(pthread_create( &GW->main_thrd.thread, &GW->main_thrd.attr, main_thread, GW)) { fprintf(stderr,"Cant create main thread <%s>\n",strerror(errno)); exit(-1); } /* * Join the threads */ pthread_join(GW->com_thrd.thread, NULL); pthread_join(GW->main_thrd.thread, NULL); return (0); } static void * main_thread(void *threaddata) { lsfgw_t *GW = NULL; GW = (lsfgw_t *)threaddata; // initialize all structures and API fprintf(stderr,"init in main Thread\n"); // sync to com_thread until it is ready if(!GW->sync_predicate) { fprintf(stderr,"Wait for complete init com thread\n"); pthread_cond_wait(&GW->sync_cond,&GW->sync_mutex); } // run the main loop fprintf(stderr,"O.K. run main Thread\n"); return; } static void * com_thread(void *threaddata) { lsfgw_t *GW = NULL; GW = (lsfgw_t *)threaddata; // Do initialize socket and fileEventLoop fprintf(stderr,"init in com Thread\n"); sleep(3); GW->sync_predicate = 1; pthread_cond_signal(&GW->sync_cond); pthread_mutex_unlock(&GW->sync_mutex); // run EventLoop fprintf(stderr,"O.K. run com Thread\n"); return; }
-
Damit wirst du irgendwann Probleme krigen. Das Prüfen der predicate variable muss geschützt werden
[cpp]
//muss weg in main
//pthread_mutex_lock(&GW->sync_mutex);static void *
main_thread(void *threaddata) {lsfgw_t *GW = NULL;
GW = (lsfgw_t *)threaddata;
// initialize all structures and API
fprintf(stderr,"init in main Thread\n");pthread_mutex_lock(&GW->sync_mutex);
// sync to com_thread until it is ready
if(!GW->sync_predicate) {// Jetzt kann der Thread nicht mehr an dieser Stelle unterbrochen
// werden und das wecken verpassen.fprintf(stderr,"Wait for complete init com thread\n");
pthread_cond_wait(&GW->sync_cond,&GW->sync_mutex);
}pthread_mutex_unlock(&GW->sync_mutex);
// run the main loop
fprintf(stderr,"O.K. run main Thread\n");return;
}static void *
com_thread(void *threaddata) {lsfgw_t *GW = NULL;
GW = (lsfgw_t *)threaddata;
// Do initialize socket and fileEventLoop
fprintf(stderr,"init in com Thread\n");
sleep(3);pthread_mutex_lock(&GW->sync_mutex);
GW->sync_predicate = 1;
pthread_cond_signal(&GW->sync_cond);pthread_mutex_unlock(&GW->sync_mutex);
// run EventLoop
fprintf(stderr,"O.K. run com Thread\n");return;
}[/cpp]
-
S.Lehner schrieb:
Damit wirst du irgendwann Probleme krigen. Das Prüfen der predicate variable muss geschützt werden
Muß sie nicht, weil nur ein Thread Schreibzugriffe macht.
Aber sie sollte als "volatile" deklariert werden.
-
@Violator
Das ist nicht der Grund, für die Verwendung dieser Mutex.
Hier der Ausschnitt des lesenden Threads:if(!GW->sync_predicate) { // Das sync_predicate ist nicht gesetzt daher gelangt der Thread an diese // Stelle. // Genau an dieser Stelle wird er vom schreiben Thread unterbrochen. // Dieser setzt das sync_predicate und weckt die Condition. // Dieser Thread kommt wieder an die Reihe und wartet in der Condition. // Das letzt Event geht also verlohren. pthread_cond_wait(&GW->sync_cond,&GW->sync_mutex); }