2008-09-16 8 views
20

Ich kodiere das Herunterfahren eines Multithread-Servers.Wenn alles so läuft, wie es sollte, verlassen alle Threads ihre eigenen, aber es gibt eine kleine Chance, dass ein Thread stecken bleibt.In diesem Fall wäre es bequem eine nicht blockierende Verbindung zu haben, damit ich es tun konnte.Non-blocking pthread_join

Gibt es eine Möglichkeit, eine nicht blockierende pthread_join zu machen? Eine zeitgesteuerte Verbindung wäre auch gut.

etwas wie folgt aus:

 
foreach thread do 
    nb_pthread_join(); 
    if still running 
     pthread_cancel(); 

kann ich mehr Fälle denken, wo ein ein nicht-bloking wäre nützlich verbinden.

Wie es scheint, gibt es keine solche Funktion, also habe ich bereits einen Workaround programmiert, aber es ist nicht so einfach wie ich es möchte.

+1

nicht blockierende Gewindeverbindung? Ich dachte, Beitritt war alles über das Blockieren: s –

Antwort

1

Wie andere darauf hingewiesen haben, gibt es in den Standard-Pthread-Bibliotheken kein nicht blockierendes pthread_join.

Allerdings wird eine solche Funktion nicht benötigt, wenn Sie Ihr angegebenes Problem (versuchen zu garantieren, dass alle Ihre Threads beim Herunterfahren des Programms beendet wurden).Sie können dies einfach tun:

int killed_threads = 0; 
for(i = 0; i < num_threads; i++) { 
    int return = pthread_cancel(threads[i]); 
    if(return != ESRCH) 
     killed_threads++; 
} 
if(killed_threads) 
    printf("%d threads did not shutdown properly\n", killed_threads) 
else 
    printf("All threads exited successfully"); 

Es ist nichts falsch mit pthread_cancel auf alle Threads aufrufen (beendet oder nicht), so fordern, dass nicht für alle Threads blockieren und Fadenausgang garantieren (sauber oder nicht).

Das sollte als eine "einfache" Problemumgehung qualifizieren.

+22

Diese Antwort ist falsch. Das erfolgreiche Aufrufen von 'pthread_cancel' in jedem Thread garantiert nicht, dass alle Threads beendet wurden. Sie haben möglicherweise keinen Abbruchpunkt erreicht, oder selbst wenn sie dies getan haben, könnte der Hauptthread zuerst eingeplant werden und von 'main' zurückkehren, um den Prozess zu beenden, bevor die anderen Threads die Bereinigung beenden können ... –

0

Sie könnten ein Byte in eine als nicht blockierend geöffnete Pipe schieben, um dem anderen Thread zu signalisieren, dass es fertig ist, und dann eine nicht blockierende Leseoperation verwenden, um den Status der Pipe zu überprüfen.

1

Die Antwort hängt wirklich davon ab, warum Sie dies tun möchten. Wenn Sie zum Beispiel nur tote Threads aufräumen wollen, ist es wahrscheinlich am einfachsten, einen "toten Thread-Cleaner" -Thread zu haben, der loopt und verbindet.

1

Ich bin mir nicht sicher, was genau Sie meinen, aber ich nehme an, dass was Sie wirklich brauchen, ein Wartemechanismus ist.

Kurz gesagt, hier ist, wie es funktioniert: Sie warten auf eine Bedingung mit einer Zeitüberschreitung zu erfüllen.

  • Der Timeout auftritt, oder
  • Wenn die Bedingung erfüllt ist: Ihr Warten wird beendet, wenn sein.

Sie können dies in einer Schleife und fügen Sie mehr Intelligenz zu Ihrer Logik. Die beste Ressource, die ich dafür in Bezug auf Pthreads gefunden habe, ist dieses Tutorial: POSIX Threads Programmierung (https://computing.llnl.gov/tutorials/pthreads/).

Ich bin auch sehr überrascht zu sehen, dass es keine API für Timed Join in Pthreads gibt.

1

Es gibt keine zeitlichen pthread_join, aber wenn Sie für anderen Thread auf Bedingungen blockiert warten, können Sie pthread_cond_timed_wait statt pthread_cond_wait

2

Wenn Sie QNX sind entwickeln, können Sie pthread_timedjoin() Funktion timed verwenden.

Andernfalls können Sie einen separaten Thread erstellen, der pthread_join() ausführt und den übergeordneten Thread alarmiert, indem Sie beispielsweise einen Semaphor signalisieren, dass der untergeordnete Thread abgeschlossen ist. Dieser separate Thread kann zurückgeben, was von pthread_join() abgerufen wird, damit der übergeordnete Thread nicht nur feststellen kann, wann das Kind den Vorgang abgeschlossen hat, sondern auch, welchen Wert er zurückgibt.

21

Wenn Sie Ihre Anwendung auf Linux laufen, können Sie interessiert sein, das wissen:

int pthread_tryjoin_np(pthread_t thread, void **retval); 

int pthread_timedjoin_np(pthread_t thread, void **retval, 
           const struct timespec *abstime); 

Seien Sie vorsichtig, da das Suffix es schon sagt, „np“ bedeutet „nicht tragbar“. Sie sind nicht POSIX-Standard, Gnu-Erweiterungen, aber nützlich.

link to man page

9

Der ‚pthread_join‘ Mechanismus ist eine Bequemlichkeit verwendet werden, wenn es genau das zu tun, geschieht, was Sie wollen. Es tut nichts, was Sie nicht selbst tun könnten, und wo es nicht genau das ist, was Sie wollen, programmieren Sie genau, was Sie wollen.

Es gibt keinen wirklichen Grund, warum Sie eigentlich interessieren sollten, ob ein Thread beendet wurde oder nicht. Was dir wichtig ist, ist, ob die Arbeit des Threads abgeschlossen ist. Um das zu sagen, lassen Sie den Thread etwas tun, um anzuzeigen, dass es funktioniert. Wie Sie das tun, hängt davon ab, was für Ihr spezifisches Problem ideal ist, was stark davon abhängt, was die Threads tun.

Beginnen Sie damit, Ihr Denken zu ändern. Es ist kein Thread, der sich festsetzt, sondern der Thread, der gerade läuft.

+0

Beispielcode bitte hinzufügen? Ich habe über das gleiche Problem, ein Prozess ruft zwei Threads und sollte nur beenden, sobald die Threads beenden - keine der Antworten hier erklärt, wie surrthing ähnlich wie die Funktion wait() von fork. (Ich habe diese Frage den Favoriten hinzugefügt, sie werden mich benachrichtigen, sobald du automatisch antwortest) –

+2

Habe einen Boolean, geschützt durch einen Mutex, der den Status der Sache speichert, die du wissen willst. Verwenden Sie bei Bedarf eine Zustandsvariable, um Sie über die Änderung des Booleschen Werts zu informieren. –

+0

Danke. Beispielcode wäre nützlich, aber ich könnte versuchen, auch woanders zu suchen. –