Frage Ist Schlaf () böse?


Vor allem gibt es viele Fälle, in denen Sleep() ist missbrauchtB. um Threads zu "synchronisieren" oder um regelmäßig einen Wert abzufragen, bei dem eine Benachrichtigungsfunktion (In Win32 WaitForSingleObject beispielsweise)

Aber was ist mit anderen Anwendungsfällen? Ist Sleep immer böse? Wenn nein, wofür sind gute Anwendungsfälle? Sleep? Wenn ja, warum haben fast alle Sprachen eine Art von Sleep Erklärung?

PS: Ich habe diese Frage wegen eines der Kommentare von Ein weiterer Frage. Dort stellt das OP fest, dass seiner Meinung nach Sleep ist wie vermieden werden goto.


40
2017-07-08 08:25


Ursprung


Antworten:


Ich glaube tatsächlich, dass die Behauptung, die Sie verbanden, richtig ist. Das Problem ist, dass der Schlaf (wie Sie festgestellt haben) als ineffizienter Ersatz für Benachrichtigungsmechanismen verwendet wird. Schlaf ist einem korrekt implementierten Benachrichtigungsmechanismus immer unterlegen, Wenn Sie auf ein Ereignis warten. Wenn Sie tatsächlich warten müssen a bestimmte Menge an Zeit für etwas, dann ist der Schlaf angemessen.

In einigen Netzwerkprotokollen verwenden Sie beispielsweise eine Technik, die als exponentieller Backoff bezeichnet wird. Wenn Sie eine Kollision im Netzwerk feststellen, möchten Sie vor dem erneuten Versuch eine zufällige (und exponentiell ansteigende) Zeitspanne warten. In diesem Fall ist der Schlaf angemessen, weil Sie nicht versuchen, auf ein Ereignis zu warten. Sie versuchen auf eine bestimmte Zeit zu warten.


40
2017-07-08 08:48



Ich habe eine gute Verwendung für die Verwendung gefunden Thread.Sleep(1000); Latenz beim Schreiben eines Callbacks in einer Webanwendung.

Ein einfaches Beispiel mit den AJAX-Komponenten von Microsoft besteht darin, eine Schaltfläche in ein Aktualisierungsfenster einzufügen. Im onclick-Handler wird Thread.Sleep () verwendet. Das Update-Fortschrittsfenster wird dann für diesen Zeitraum angezeigt.

Entfernen Sie das Thread.Sleep () bei der Live-Übertragung. :)


20
2017-07-08 08:35



In der realen Welt ist es nicht immer praktisch, die richtigen Synchronisationsgrundelemente zu verwenden:

  • Manchmal müssen Sie etwas abfragen, bis eine Bedingung erfüllt ist und Sie verwenden sleep um ein Einweichen der Maschine zu vermeiden.

  • Manchmal bist du aktiv wollen zu schlafen - zum Beispiel, wenn ein Thread minimale Maschinenressourcen benötigt und Sie auf einem Betriebssystem sind (Husten Windows Husten), die nicht sehr gut daran arbeiten, zu verhindern, dass Threads mit niedriger Priorität die Maschine durchnässen.

Bearbeiten als Reaktion auf Kievelis Kommentar: Ich denke an dich sollte implementieren Sie richtige Signalisierung, wenn Sie können. Daher sollte ein Worker-Thread eine blockierende Leseoperation in einer Warteschlange ausführen, statt zu schlafen und zu pollen. Ich sage, dass man manchmal gezwungen ist, mit Systemen zu interagieren ausschließen das Richtige tun. Ich sage nicht, dass man sich nicht die Mühe machen sollte, das Richtige zu tun, wenn es vernünftigerweise möglich ist - "innerhalb einer halben Sekunde ist es gut genug", vielleicht, aber fast augenblicklich wäre merklich besser!


19
2017-07-08 08:29



Gleiche Antwort wie für alle anderen "ist es böse" Fragen.

Es ist eine Low-Level-Operation. Leute benutzen manchmal Low-Level-Operationen, um Räder neu zu erfinden, die bereits als High-Level-Operationen verfügbar sind. Das ist unklug, und Sie sollten sicherstellen, dass es nicht das ist, was Sie tun. Aber wenn Sie tatsächlich auf niedriger Stufe programmieren, werden Sie wahrscheinlich Low-Level-Operationen verwenden. Einige High-Level-Programmierer werden denken, du bist böse oder dumm oder beides. Du weißt es besser, und da du derjenige bist, der ihre High-Level-Plattformen schreibt, können sie entweder den Mund halten oder es selbst tun.

Angesichts der Wahl zwischen einer bösen Kontorsion, die ein High-Level-Konstrukt verwendet, und einer bösen Kontorsion, die ein Low-Level-Konstrukt verwendet, denken einige Leute, dass Sie immer die erste bevorzugen sollten. Ich bekomme ihren POV nicht wirklich, aber sie sind zumindest konsistent, also kannst du ihnen keine Vorwürfe machen, es sei denn, letzterer ist nachweislich schneller / kleiner / besser.

Gute Anwendungen für den Schlaf:

  • Wenn Sie bis zu einer bestimmten Zeit (oder für eine bestimmte Zeit) blockieren müssen. Ihre Sprache / Bibliotheken / Betriebssysteme bieten möglicherweise einen Sperrzeitgeber, der diese Aufgabe erfüllt. Wenn nicht, dann ist Schlaf die immer verfügbare Option. Wenn dem so ist, wird es wahrscheinlich genau das selbe tun, was die Mood-Standard-Schlafschleife sowieso macht, also geh mit was auch immer weniger Code ist.

  • Wenn andere Grundelemente wie Timer implementiert werden.

  • Wenn Sie Signale für asynchrones Inter-Thread- oder Interprozess-Messaging auf POSIX oder was auch immer verwenden. Du schläfst nur die ganze Zeit, und Signalhandler erledigen entweder die Arbeit oder setzen den Status, um dir zu sagen, was Arbeit zu tun hat und du tust es, wenn du aufwachst. Natürlich könntest du stattdessen andere APIs verwenden, aber wenn du diese API nicht aktiv bevorzugst, dann würdest du nur den Schlaf vermeiden, weil ein Typ im Internet es dir gesagt hat. Vielleicht, wenn er eine Programmiersprache schreibt, die keinen Schlaf hat und besser ist als Ihre aktuelle Sprache, dann wechseln Sie dazu.

Das Hauptproblem mit dem Schlaf (abgesehen davon, dass es nicht wirklich viel Interaktion zwischen Threads macht, ist also normalerweise das falsche Werkzeug für Jobs, die das erfordern) ist, dass Sie immer noch Ressourcen verbrauchen, obwohl Sie keine CPU-Zeit verbrauchen weil du einen Thread sitzt, der nichts tut. Je nach Plattform können Threads teuer sein. Auf einem Single-Core-System ist der zweite Thread von zwei besonders teuer, denn wenn Sie ihn loswerden können, gehen die meisten Probleme bei der Datensynchronisation verloren. Wenn Sie also Ihre App vernünftig so gestalten können, dass sie nie mehrere Threads benötigt und niemals blockiert, außer in einer Ereignisschleife, weil alles mit asynchronen Nachrichten erfolgt, tun Sie dies, und Sie brauchen keinen Schlaf.


8
2017-07-08 08:30



Die Implementierung von tail -f würde erfordern a sleep(). d.h. stat() die Datei, wenn sie sich geändert hat, lies dann die Unterschiede ein sleep() für ein bisschen ...... weiter bis unterbrochen.

Ich würde dies als eine gültige Verwendung von betrachten sleep()

Als Beispiel für Linux, strace tail -f foo, setzt sich auf

clock_gettime(CLOCK_REALTIME, {1247041913, 292329000}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat64(3, {st_mode=S_IFREG|0755, st_size=357, ...}) = 0
clock_gettime(CLOCK_REALTIME, {1247041914, 311933000}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat64(3, {st_mode=S_IFREG|0755, st_size=357, ...}) = 0
clock_gettime(CLOCK_REALTIME, {1247041915, 355364000}) = 0
....

OK, das ist es nanosleep() aber es gelten die gleichen Regeln.

Solaris truss tail -f foo setzt sich auf

read(0, 0x00024718, 65537)                      = 0
nanosleep(0xFFBFF1A0, 0xFFBFF198)               = 0
read(0, 0x00024718, 65537)                      = 0
nanosleep(0xFFBFF1A0, 0xFFBFF198) (sleeping...)
nanosleep(0xFFBFF1A0, 0xFFBFF198)               = 0
read(0, 0x00024718, 65537)                      = 0

7
2017-07-08 12:57



Abgesehen von Testzwecken wie dem von ChalkeyIch habe festgestellt, dass ich nie wirklich anrufen muss Schlaf auf High-Level-Betriebssystemen wie Linux, Windows und OS / X. Sogar in Fällen, in denen erwartet wird, dass das Programm einfach auf eine bestimmte Zeit wartet, verwende ich a warten Funktion an einem Semaphor mit einem Timeout, so dass ich den Thread sofort beenden kann, indem ich den Semaphor loslasse, wenn jemand / jemand mein Programm zum Beenden auffordert:

# [pseudo-code]

if wait_semaphore(exit_signal_semaphore, time_to_sleep)
  # another thread has requested this one to terminate
  end_this_thread
else
  # event timed-out; wait_semaphore behaved like a sleep function
  do_some_task
end

5
2017-07-08 13:23



Ich kann nicht sehen, dass es hier erwähnt wird, aber sleep () ist ein ziemlich sicherer Weg, um Ihre CPU-Zeitscheibe zu mehr würdigen Prozess zu bringen. Wenn Sie schlafen (), übernimmt das Betriebssystem die Kontrolle und entscheidet, wer als nächstes ausgeführt werden soll. Dadurch können auch andere Threads desselben Prozesses CPU-Zeit haben. Dies erleichtert den CPU-Druck auf Single-CPU-Maschinen, wenn mehrere Threads erzeugt werden und ein Controller darauf wartet, dass Workers bereit sind.


5
2017-07-08 08:30



Wenn Sie Sleep () verwenden, um mit jedem Fall zu arbeiten, der mehr als nur den Thread betrifft, in dem Sie arbeiten, besteht die Möglichkeit, dass Sie etwas falsch machen ...

Das heißt, es gibt Zeiten, in denen Sie die Verarbeitung anhalten möchten, zum Beispiel in einer endlosen (oder tatsächlich so) Arbeitsschleife, um anderen Prozessen etwas Luft zum Atmen zu geben.


4
2017-07-08 08:30