Wie kann man einen Pthread anhalten und fortsetzen?

8

Ich schreibe in C (eigentlich in OOC, das dann zu C kompiliert wird).

Wie weise ich einen Thread an, an einem bestimmten Prüfpunkt zu warten, bis ein anderer Thread ihn anweist, fortzufahren?

Ich benutze tatsächlich eine enge Schleife im Thread und pole eine Variable, die ich vom Hauptthread ändere, aber ich denke, das ist nicht gut, oder? Abgesehen davon, wenn ich eine enge Schleife in einem Thread mache, sollte ich einen Schlaf in die Schleife aufnehmen, um zu vermeiden, dass viel CPU-Power verbraucht wird, nur Schleifen?

    
Damian 25.01.2011, 14:56
quelle

4 Antworten

10

Es scheint, dass Sie nach pthread_cond_wait und den zugehörigen Funktionen suchen.

Hier ist ein Zitat aus der Hilfeseite mit einem Beispiel:

  

Betrachten Sie zwei gemeinsam genutzte Variablen x und y, die durch den Mutex mut geschützt sind, und eine Bedingungsvariable cond, die signalisiert werden soll, wenn x größer als y wird.

%Vor%      

Warten bis x größer als y ist, wird wie folgt ausgeführt:

%Vor%      

Änderungen an x ​​und y, die dazu führen können, dass x größer als y wird, sollten den Zustand bei Bedarf signalisieren:

%Vor%

Am Ende macht es das, wonach Sie fragen: Der Thread, der pthread_cond_wait(&cond) aufruft, ist blockiert, bis ein anderer Thread (zB Ihr Haupt-Thread) pthread_cond_broadcast(&cond) aufruft. Während dieser Zeit befindet es sich nur im blocked -Zustand und verbraucht keine CPU-Zyklen.

    
arnaud576875 25.01.2011, 15:03
quelle
2

Ich denke, das ist ein guter Kandidat für eine Bedingung. Der Thread sollte auf eine Bedingung warten und der andere Thread sollte die Bedingung signalisieren, damit dieser Thread fortgesetzt wird.

Sie können pthread_cond_init nachschlagen und das sollte zu anderen Funktionen führen

    
vmpstr 25.01.2011 15:02
quelle
2

Sie sollten in geeignete Synchronisationsgrundelemente wie Mutexe, Zustandsvariablen und Semaphore schauen. In diesem Fall klingt es wie eine Bedingungsvariable , die aus der Pthreads-Bibliothek am besten geeignet ist.

>     
pmdj 25.01.2011 15:04
quelle
1

Nur damit Sie wissen, was vor sich geht, verbraucht eine "enge Schleife" die CPU-Zuteilung Ihres Threads genau wie jeder andere Code, den Ihr Thread ausführt. Der einzige Unterschied ist, dass es nichts bewirkt. Nun, ich schätze, dass es eine Sache ist, den Kern warm zu machen ... Wahrscheinlich wirst du das nie tun wollen, außer du interessierst dich für die Kosten des Kontextwechsels und weißt sicher , dass die Wartezeit viel wird kürzer als der Zeitschlitz deines Threads, der ungefähr 1 ms ist. Ich weiß nicht, ob der Schlaf so schlecht ist wie der Ertrag (der AFAIK-Ertrag setzt den Thread auf der Rückseite der Liste der Threads, die auf der Prioritätsstufe aktiviert werden sollen), aber beide verursachen zumindest den Nachteil eines Kontextwechsels. Es gibt Kosten für den Kontextwechsel. Ein Kontextwechsel ist der Fall, wenn der Zeitschlitz des Threads endet. Es kann entweder enden, weil Sie es mit einem Ertrag oder einem Schlaf beendet haben, oder wenn der Kernel es beendet hat, indem er Sie vorweggenommen hat. Lesen Sie mehr über SMP und Spinlocks, um mehr über Kontextwechsel und Fälle zu erfahren, wenn eine enge Schleife anwendbar ist.

Auch wenn du schläfst, weißt du nicht genau, wann du wieder aufwachst. Ein Grund, warum Sie nicht schlafen wollen, ist, dass Sie etwas schnell erledigen müssen. Sie könnten ein paar Millisekunden warten, bevor Sie neu geplant werden.

Alle anderen gaben Ihnen die Lösung pthread_cond_wait, die eine Sperrung über Mutexe erfordert und einfach und unkompliziert aussieht. Die Leistung ist möglicherweise für Ihre Anforderungen ausreichend, ist aber im Vergleich zu einer Lösung mit Signalen relativ langsam ( sigwait und pthread_kill ). Die Komplexität wird sich an dich heranwagen.

Hier wird nicht erläutert, warum Sie vor dem Testen einen Mutex sperren, wenn Sie auf die Bedingung warten müssen. Der Grund ist, dass Code wie dieser einen Fehler hat:

%Vor%

Ihr Thread könnte testen (X & lt; = Y), Sie müssen sehen, dass er warten muss, aber er muss vorverarbeitet werden, bevor er sich an den Zustandswert anfügt. Ein anderer Thread, der gerade X oder Y modifiziert hat, signalisiert die Bedingung in diesem Zeitfenster, bevor der erste Thread sich an die Bedingung anfügt. Auf diese Weise geht das Zustandssignal verloren. Was letztendlich geschieht, ist überall dort, wo Sie die Variablen verändern, die das Signal beeinflussen, Sie müssen Sperren hinzufügen.

%Vor%

Dies kann bedeuten, dass Sie diese Mutex-Locks an vielen verschiedenen Stellen hinzufügen und Ihr Code dadurch komplexer und langsamer wird. Die Möglichkeit, dass ein aufgehängter Faden auf eine Bedingung wartet, ist immer da. Die Loop-, Test-, Sleep-Lösung hat keines dieser Probleme. Wenn also die Wartezeit bekanntlich kurz ist, ist die Verwendung von Schlaf in einer Schleife wahrscheinlich eine gute Lösung. Vor allem, wenn Sie zwischen den Tests eine Sekunde oder länger schlafen können. Wenn du kannst, dann kümmere dich nicht um Mutexe und Bedingungen. Wenn die Schlafzeit kurz ist, wie 1ms und die Wartezeit lang ist, wie Minuten oder Stunden, dann werden Sie am Ende einige Ressourcen verschwenden, indem Sie ständig aufwachen und wieder schlafen gehen. Du musst urteilen.

Beachten Sie auch, dass der Kernel manchmal versucht, den Kellner-Thread sofort zu wecken, und manchmal wird es eine Verzögerung geben. Wenn der Thread zu früh aufwacht, wird er aktiviert, während der Mutex gesperrt ist, und sofort wieder in den Ruhezustand versetzt, bis der Mutex entsperrt wird. Wenn das ein Problem wird, signalisieren Sie die Bedingung:

%Vor%

Danke an user576875, dessen Code-Beispiele ich kopiert habe.

    
johnnycrash 25.01.2011 16:11
quelle

Tags und Links