Nur damit Sie wissen, was los war, verbraucht eine "strenge Schleife" Ihre Thread-CPU-Zuweisung genauso wie jeder andere Code, den Ihr Thread ausführt. Der einzige Unterschied besteht darin, dass sie nichts erreicht. Nun ja, ich nehme an, den Kern warm zu machen, ist etwas... Sie möchten das wahrscheinlich nie tun, es sei denn, Sie kümmern sich um die Kosten des Kontextwechsels und Sie wissen sicher, dass die Wartezeit viel kürzer sein wird als die Zeitscheibe Ihres Threads, die etwa 1 ms beträgt. Ich weiß nicht, ob Sleep genauso schlimm ist wie Yield (soweit ich weiß, setzt Yield Ihren Thread ans Ende der Liste der Threads, die auf Ihrer Prioritätsebene aktiviert werden), aber beide verursachen zumindest die Strafe eines Kontextwechsels. Es gibt Kosten für den Kontextwechsel. Ein Kontextwechsel tritt ein, wenn die Zeitscheibe Ihres Threads endet. Dies kann entweder geschehen, weil Sie sie mit einem Yield oder einem Sleep beendet haben oder wenn der Kernel Sie präemptiert hat. Lesen Sie über SMP und Spinlocks, um mehr über Kontextwechsel und Fälle zu erfahren, in denen eine strenge Schleife anwendbar ist.
Außerdem, wenn Sie schlafen, wissen Sie nicht genau, wann Sie wieder aufwachen. Ein Grund, warum Sie vielleicht nicht schlafen möchten, ist, dass Sie etwas schnell erledigen müssen. Sie könnten ein paar ms warten, bevor Sie neu geplant werden.
Jeder andere hat Ihnen die Lösung mit pthread_cond_wait gegeben, die eine Sperre über Mutexe erfordert und einfach und unkompliziert aussieht. Die Leistung könnte für Ihre Bedürfnisse ausreichend sein, ist jedoch im Vergleich zu einem Lösungsansatz mit Signalen relativ langsam (sigwait und pthread_kill). Die Komplexität kommt langsam auf Sie zu.
Hier wird nicht diskutiert, warum Sie ein Mutex sperren, bevor Sie testen, ob Sie auf die Bedingung warten müssen. Der Grund ist, dass Code wie dieser einen Fehler hat:
while (x <= y) {
pthread_cond_wait(&cond, &mut);
}
Ihr Thread könnte prüfen (X<=Y), sehen, dass er warten muss, aber vor dem Anhängen an den Bedingungswert preemtiert werden, bevor ein anderer Thread, der gerade x oder y geändert hat, das Signal in diesem Zeitscheibe vor dem Ersten an die Bedingung heftet. Auf diese Weise geht das Bedingungssignal verloren. Daher müssen überall, wo Sie die Variablen ändern, die das Signal beeinflussen, Sperren hinzugefügt werden.
pthread_mutex_lock(&mut);
/* X und Y ändern */
if (x > y) pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
Dies bedeutet, dass Sie diese Mutex-Sperren an vielen verschiedenen Stellen hinzufügen und Ihr Code aufgrund dessen komplexer und langsamer wird. Die Möglichkeit eines hängenden Threads, der auf eine Bedingung wartet, besteht immer. Die Schleifen-, Test-, Schlaf-Lösung hat keine dieser Probleme. Wenn die Wartezeit kurz ist, ist die Verwendung von Sleep in einer Schleife wahrscheinlich eine gute Lösung. Insbesondere, wenn Sie zwischen den Tests eine Sekunde oder mehr schlafen können. Wenn Sie dies können, dann kümmern Sie sich nicht um Mutexe und Bedingungen. Wenn die Schlafzeit kurz ist, wie 1 ms, und die Wartezeit lang ist, wie Minuten oder Stunden, werden Sie letztendlich einige Ressourcen verschwenden, indem Sie kontinuierlich aufwachen und wieder einschlafen. Sie müssen abwägen.
Außerdem ist zu beachten, dass der Kernel manchmal versucht, den wartenden Thread sofort zu wecken und manchmal eine Verzögerung auftritt. Wenn der Thread zu früh aufwacht, wird er aufwachen, während das Mutex gesperrt ist, und sofort wieder einschlafen, bis das Mutex entsperrt ist. Wenn das zum Problem wird, signalisieren Sie die Bedingung auf diese Weise:
pthread_mutex_lock(&mut);
/* X und Y ändern */
if (x > y) {
pthread_mutex_unlock(&mut);
pthread_cond_broadcast(&cond);
} else
pthread_mutex_unlock(&mut);
Danke an Benutzer576875, dessen Codebeispiele ich kopiert habe.