PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : pthread - Warten auf Bedingungen



thommy
09-07-2001, 08:43
Mit pthread_cond_wait kann die Ausführung eines Threads bis zum Eintritt einer bestimmten Bedingung blockiert werden. Gibt es eine Möglichkeit, gleichzeitig mehrere Bedingungen zu überwachen und den Thread zu reaktivieren, sobald eine dieser Bedingungen gegeben ist?

Thomas

jgbauman
09-07-2001, 15:06
Im folgenden Beispiel wird mit einer Condition auf zwei verschiedene Bedingungen gewartet: x<=y und a<=b .
Allerdings muessen jetzt alle Aenderungen an x,y,a,b unter dem gleichen Mutex ablaufen, was die Paralellitaet beeintraechtigt.
Eine Loesung waere mit Schattendaten sx und sy unter einem Mutex M1 und sa und sb unter Mutex M2 zu arbeiten und nur das Schreiben der entgueltigen Daten von dann Schattendaten in die richtigen Stellen x,y,a,b unter den Mutex M3 zu stellen der auch von der Condition benutzt wird.

Wenn beim signal/broadcast jede Bedingung bekannt ist, faehrst Du vielleicht mit einem Message-passing ueber eine synchronisierte Warteschlange/Buffer besser.

Schreib doch einfach mal mehr ueber deinen speziellen Fall. Allgeine Aussagen ueber effektive Synchronisierung sind IMHO unmoeglich.


int x,y,a,b;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

...

pthread_mutex_lock(&mut);
while ((x &lt;= y) &#0124;&#0124; (a &lt;= b)){
pthread_cond_wait(&cond, &mut);
}

/* operate on x y, and z */
pthread_mutex_unlock(&mut);

...

pthread_mutex_lock(&mut);
x = value;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);

...

pthread_mutex_lock(&mut);
y = value;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);

...

pthread_mutex_lock(&mut);
a = value;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);

...

pthread_mutex_lock(&mut);
b = value;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);

thommy
09-07-2001, 16:16
Danke für die Hinweise...

Konkret sitze ich an der Portierung einer Windows-Anwendung, wobei dort mit WaitForMultipleObjects mehrere "Handles" überwacht werden. Ein solches Handle lässt sich nach der von Dir beschriebenen Methode über Mutexes simulieren, womit sich das Eventhandling bez. eines einzelnen "Events" analog zu Windows realisieren lässt (ein WaitForSingleObject läuft bereits zuverlässig).

Nun greift die Anwendung an verschiedenen Stellen auf einunddieselben Handles zu, nur halt in verschiedenen Kombinationen (bspw. soll ein Thread auf Terminierung UND eine neue Nachricht warten; an anderer Position jedoch auf Terminierung und neue Konfigurationsdaten...). Für jede erdenkliche Kombination die Bedingungen in eigene Mutexes zu packen, ist mir dann doch zu aufwändig.


Aber soweit meine Netzrecherche berichtet, existiert keine "einfache" Lösung für das Problem, da Windows das Handling im Kernel unterstützt. Scheint so, als muss ich die entsprechenden Passagen komplett neu schreiben;(


Thomas

jgbauman
09-07-2001, 17:57
Folgender Loesungsansatz:
Jeder Thread besitzt ein spezielles Blockierungsobjekt (Condition/Mutex/evt Data).
Jedes Handle besitzt eine Warteschlange.

Ein WaitForMultipleObjects reiht das Blockierungsobjekt in die Warteschlangen aller zu beachtender Handles ein und blockiert sich an seinem Blockierungsobjekt.

Ein Signal von einem Handle bewirkt eine Signalierung aller Blockierungsobjekte in der Warteschlange eines Handles.

Das blockierte WaitForMultipleObjects wacht auf und entfernt sein Blockierungsobjekt aus allen Warteschlangen der zu beobachtenden Handles. Im Data-Feld des Blockierungsobjekts kann auch einer der signalisierenden Handles vermerkt sein. Aber genaue Angaben bei mehrfacher signaliesierung bietet das Windows-Interface auch nicht. (Ausser dass es dann das Handle mir dem niedrigsten Index als aufweckendes angiebt).

Wenn Du viel mit Threads unter Linux arbietest interessiert dich vielleicht auch folgender Link: http://oss.software.ibm.com/developerworks/opensource/pthreads/

Wenn Du auf Termination wartest hilft dir vielleicht:
man pthread_setcanceltype

thommy
11-07-2001, 09:28
Dass mit WaitForMutipleObjects werde ich vorerst auf die lange Bank schieben, sonst müsste ich die Threadklassen an zu vielen Stellen ändern. Aber der Ansatz ist interessant und ich werde mich, wenn es mal wieder die Zeit erlaubt, daran versuchen.

Die Informationen in dem Link habe ich nur mal kurz überflogen, habe ich keinen Hinweis gefunden, ob die dortige Threadrealisierung im Nutzermodus oder im Kernel läuft. Wie ist da eigentlich der derzeitige Status der pthread-Bibliothek? Greift sie endlich auf clone() zu?

Zur Terminierung: Ich greife bei der Initialisierung sofort auf pthread_detach() zurück, um die Ressourcen automatisch bei Beendigung des Threads freizugeben. Das scheint auch zuverlässig zu funktionieren...

Danke
Thomas

jgbauman
11-07-2001, 09:45
Wie da auf der ersten Seite steht wird da M:N-Threading unterstuetzt (M Aktivitaetstraeger laufen auf N Kernaktivitaetstraeger verteilt).
AFAIK sind damit aber auch 1:1 (Kernel-Threads) und M:1 (pure user-spave threading) moeglich.