boost::threads - nicht unterbrechbar?



  • Ich verwende die boost Bibliothek um mit Threads unter C++ zu programmieren. Am meisten hat mir dabei die Anleitung von highscrore.de gebracht:
    http://www.highscore.de/cpp/boost/multithreading.html

    Nun heißt es dort aber, dass es nur ca. 10 Punkte gibt an denen ein Thread unterbrochen werden kann (z.B. wenn er auf ein wait() stößt). Ansonsten sei dies nicht möglich.
    Ich frage mich nun auf welcher Ebene sich das abspielt. Denn eigentlich bestimmt ja der Scheduler im Kernel wann welcher Thread Prozessorzeit bekommt (z.B. mit timeslices). Erstellt die boost lib dann non-preemtive threads die wirklich vom Scheduler nicht unterbrochen werden?



  • Das hat mit Scheduling nichts zu tun, da geht es um das "kooperative Abbrechen" von Threads, also wenn du den Thread sauber von aussen beenden möchtest.



  • hustbaer schrieb:

    Das hat mit Scheduling nichts zu tun, da geht es um das "kooperative Abbrechen" von Threads, also wenn du den Thread sauber von aussen beenden möchtest.

    Tut mir Leid, das verstehe ich nicht. Kannst du das etwas ausführlicher erklären? Wer will wen abbrechen und auf welcher Ebene? Wann ist ein Thread also zwischen den Unterbrechungspunkten nicht unterbrechbar? Der Scheduler kann den Thread unterbrechen wo er will?



  • fabske schrieb:

    Der Scheduler kann den Thread unterbrechen wo er will?

    Richtig.

    fabske schrieb:

    Nun heißt es dort aber, dass es nur ca. 10 Punkte gibt an denen ein Thread unterbrochen werden kann (z.B. wenn er auf ein wait() stößt).

    Das müste heißen, es gibt ca. 10 Punkte an denen der Thread von außen abgebrochen werden kann (mittels interrupt-Exception). Hat nix mit den Unterbrechungen durch den Sceduler zu tun, der kann tun und lassen was er will.


  • Administrator

    pumuckl schrieb:

    Das müste heißen, es gibt ca. 10 Punkte an denen der Thread von außen abgebrochen werden kann (mittels interrupt-Exception). Hat nix mit den Unterbrechungen durch den Sceduler zu tun, der kann tun und lassen was er will.

    Ich würde die Hervorhebung anders setzen:
    Das müsste heißen, es gibt ca. 10 Punkte an denen der Thread von außen abgebrochen werden kann (mittels interrupt-Exception). Hat nix mit den Unterbrechungen durch den Sceduler zu tun, der kann tun und lassen was er will.

    Einen Thread kann man auch anders abbrechen. Der Thread könnte zum Beispiel eine Variable regelmässig prüfen und sich dann selber beenden, wie man dies auch normalerweise tun sollte. interrupt ist doch nur dazu da, um einen Thread aufzuwecken, welcher aktuell in einem Wartezustand ist und beendet werden soll. Statt dass er normal aus dem Wartezustand herauskommt, wirft er eine Exception, damit man auch erkennen kann, dass ein interrupt aufgerufen wurde. Es geht also nur um das Abbrechen aus dem Wartezustand.

    Grüssli



  • Zuerstmal vielen Dank für die Antworten! Ich muss das unbedingt verstehen. Ich frage mich warum bei boost hervorgehoben wird, dass man nur an diesen ca. Unterbrechungspunkten den Thread unterbrechen kann. Welche Vorteile hat das oder worauf zielt das ab?

    Es geht um das Abbrechen im Wartezustand

    von außen abbrechen

    Wikipedia:

    Eine Unterbrechungsanforderung oder englisch Interrupt Request (IRQ) löst eine Unterbrechung (Interrupt) der Prozessbearbeitung eines Prozessors im System aus. In der Regel wird diese von Geräten im System durch eine Busleitung mit Namen IRQ signalisiert und der Prozessor reagiert mit einem Kontextwechsel und führt die Unterbrechungsroutine aus. Nach deren Beendigung wird IRQ zurückgesetzt und die unterbrochene Aufgabe fortgesetzt.

    Der Scheduler ist ja Teil des Kernels. Mit "von außen" meint ihr nun andere Prozesse die dem Prozess mittels Signal etwas mitteilen wollen (z.B. beende dich), ja?.
    Aber welchen Wartezustand meint ihr denn? Den Wartezustand im Scheduler ja wohl nicht? Dann das Warten auf auf z.B. I/O?



  • fabske schrieb:

    Zuerstmal vielen Dank für die Antworten! Ich muss das unbedingt verstehen. Ich frage mich warum bei boost hervorgehoben wird, dass man nur an diesen ca. Unterbrechungspunkten den Thread unterbrechen kann. Welche Vorteile hat das oder worauf zielt das ab?

    Es liegt es afaik an der Ressourcen-Freigabe. Wenn ein Thread einfach gestoppt
    würde, werden keine Destruktoren mehr aufgerufen, Mutexe nicht entsperrt und Ressourcen
    nicht wieder freigegeben.

    Ein Wartezustand ist nichts anderes als ein regelmäßiges Überprüfen einer
    bestimmten Bedingung. (Hier wohl ein einfacher boolean). Wenn der geforderte
    Zustand eintritt (z.B. Thread-Stopp-Dich), dann reagiert er dementsprechend
    (Hier wirft er eine Exception)

    Die Kommunikation von den Threads läuft (in diesem Fall) allein über das
    Setzen bestimmter WErte im Arbeitsspeicher, die von dem anderen Thread
    (regelmäßig) überprüft werden.



  • Ich glaube so langsam sehe ich Licht am Ende des Tunnels! Ich würde aber noch gerne wissen wer dafür zuständig ist!

    Also ich programmiere beispielsweise eine Anwendung mit 3 Threads. Die Threads laufen in Schleifen und einer von Ihnen versucht PI zu berechnen. Das heißt dieser Thread wird niemals mit seiner Berechnung fertig. Falls die anderen auf eine Freigabe eines Mutex warten das von diesem Thread blockiert wird, werden sie wohl ewig warten.

    Wie verhält sich nun der Scheduler? Lässt er immer diesen einen Thread der PI berechnet rechnen, und ruft die anderen beiden gar nie mehr auf, da sie ja nichts machen können und auf den Mutex warten, oder wird allen drei Threads immer wieder Prozessorzeit zur Verfügung gestellt? Die beiden wartenden Threads machen dann eben nichts anderes, als kurz zu schauen ob der Mutex frei ist, und da er nicht frei ist geben sie die Prozessorzeit wieder ab.

    Wer macht hier in welchem Fall was? Wofür ist boost verantwortlich und wofür die Threading-Bibliothek und wofür der Scheduler?



  • Das kommt auf die Art der Mutex an.

    Bei einem SpinLock werden die wartenden Threads hübsch im Kreis laufen und mächtig CPU Zeit vernichten.

    Bei nem SpinSleepLock werden sie ein paar tausend mal in Kreis laufen, und sich dann heia legen (so dass sie erst vom Scheduler aufgeweckt werden wenn die Mutex freigegeben wurde).
    Und bei nem reinen SleepLock gehen sie sofort heia.

    Und du kannst davon ausgehen, dass keine Library dir einen reine Spinlock unterjubeln wird, wenn du nicht explizit danach fragst.
    D.h. normalerweise bekommst du nen SleepLock oder SpinSleepLock.

    Unter Windows ist CRITICAL_SECTION per Default z.B. ein SleepLock, kann aber zu einem SpinSleepLock gemacht werden, wenn man InitializeCriticalSectionAndSpinCount statt InitializeCriticalSection zum initialisieren verwendet.
    Die Windows Kernel Mutexen (CreateMutex() und so) sind reine SleepLocks (und noch dazu reine Kernel-Objekte, also langsam, aber darum geht's ja hier nicht).

    Die Boost-Thread Mutexen sind seit einigen Versionen soweit ich weiss SpinSleepLocks, und zwar unabhängig vom OS (vorausgesetzt der Compiler unterstützt Interlocked-Instructions, was mit MSVC und GCC auf x86 kein Problem ist).



  • Aha, ganz neue Begriffe die ich gleich mal im Wiki nachgeschaut hab! "spinlock" scheint ja Vor- und Nachteile zu haben, da ein Threadwechsel teuer ist.

    Das heißt falls mein boost Sleeplocks verwendet schlafen die Threads auch wirklich solange bis der lock auf den sie warten frei ist, und wachen nicht immer wieder auf um zu schauen ob er frei ist.

    In welchem Zusammenhang stehen da nun die sogenannten Futexe?

    Die Synchronisation der Prozesse besteht nun darin, dass im Allgemeinen ein Prozess auf ein Ereignis warten muss, das von einem anderen ausgelöst wird. Es ist Aufgabe des Schedulers, die sich daraus ergebenden kausalen Abhängigkeiten so umzusetzen, dass ein Prozess immer nur dann Rechenzeit bekommt, wenn alle dafür notwendigen Bedingungen erfüllt sind. Konkret wird dies meist durch die klassischen Kontrollmechanismen wie Locks, Semaphore und Monitore gelöst.

    Also arbeitet der Scheduler nicht komplett unabhängig von dem was ich programmiere!? Er versucht anhand meiner Logs die Threadwechsel zu optimieren?


Log in to reply