existierender Thread auf kommando starten bis arbeit getan ist dann wieder warten?



  • Mach mal ein Beispiel für die ..., die zu einem Deadlock fürhen würden.

    ----

    Die klassischste Variante, die zum Deadlock führt, sieht so aus:

    void foo()
    {
       lock (a) { lock (b) { ... } }
    }
    
    void bar()
    {
       lock (b) { lock (a) { ... } }
    }
    

    Wenn ein Thread foo ausführt und einer bar, der erste Thread a schon bekommen hat, aber noch nicht b, der zweite Thread b schon bekommen hat, aber noch nicht a, dann habe ich einen Deadlock, weil jetzt die beiden Threads auf etwas warten, was der jeweils andere Thread gelockt hält.



  • Ein

    lock(this)
    {
    }
    

    kann dann zum Deadlock führen, wenn die Instanz, die this bezeichnet, von jemand fremden als Lock Variable missbraucht wird.

    http://www.toolazy.me.uk/template.php?content=lock(this)_causes_deadlocks.xml
    http://srtsolutions.com/blogs/billwagner/archive/2007/09/09/why-lock-this-is-bad.aspx



  • Wenn's MFC wäre würde ich's so machen:

    UI thread starten
    wenn er aktiv ist sendet er mit PostMessage: I_AM_BORED
    dann schickt ihm der main-thread 'ne PostThreadMessage: DO_ANYTHING
    job erledigt - thread sendet PostMessage: I_AM_BORED
    usw. usf.

    wobei ich die jobs einfach in einer std::queue speichern würde

    aber weil ich C# nicht kann (und nicht mag) ist das eine Antwort, die ich mir eigentlich hätte schenken können :p



  • Knuddlbaer schrieb:

    http://www.toolazy.me.uk/template.php?content=lock(this)_causes_deadlocks.xml

    OK, wo ist da der Deadlock?
    Deadlock bedeutet, dass ich für immer auf einen Lock warte. Ich sehe gerade nicht, wie das bei dem Code passieren sollte.

    @Boris: Ansonsten zu der Queue:

    NewJob: Queue 'lock'en, enqueuen, queue 'pulse'n, (wird wieder entlockt)

    Eine Aufgabe entnhemen: Queue 'lock'en, wenn leer auf Queue 'wait'en, Element entnehmen, (wird wieder entlockt)

    Der Arbeiter-Thread (also dein SynchronWork, welches nicht synchron sonder asynchron arbeitet) versucht einfach die ganze Zeit in einer Schleife etwas aus der Queue zu entnehmen und es dann zu bearbeiten.



  • @Helium: ja das mit dem deadlock ahb ich verstanden danke;)

    Bei diesem Beispiel:

    A:

    lock (foo) {
       ...
    }
    

    B:

    Monitor.Enter(foo);
    try {
       ...
    }
    finally {
       Monitor.Exit(foo);
    }
    

    würd in A eine exception lock block auftreten, würde der lock bleiben?? Bei B würde der lock auch aufgehoben werden, wenn ne exception auftritt? hab ich das richtig verstanden?



  • Ein lock-Block entsperrt immer, wenn der Block verlassen wird (egal wie!). Vgl. RAII in C++.

    Ein finally-Block wird immer ausgeführt, wenn der zugehörige try-Block verlassen wird (egal wie!).



  • hmm.. ok wenn bspw.:

    Monitor.Enter(foo);
    
    try {
       ...
    }
    catch(...){
    
    }
    
    Monitor.Exit(foo);
    

    ohne das finally, gehts doc hauch???



  • BorisDieKlinge schrieb:

    hmm.. ok wenn bspw.:

    Monitor.Enter(foo);
    
    try {
       ...
    }
    catch(...){
    
    }
    
    Monitor.Exit(foo);
    

    ohne das finally, gehts doc hauch???

    Nein. finally ist GARANTIERT das es ausgeführt wird.

    In diesem Beispiel dagegen kommt es drauf an was in den [...] passiert.

    Wenn z.B. der try-block mit einem return verlassen wird hast Du schon verloren. Oder wenn im catch nciht alle Exceptions abgedeckt werden die geworfen werden könnten hast Du schon wieder verloren.



  • Und bei dieser Variante?

    lock(...){
    
    try {
       ...
    }
    catch(...){
    
    } 
    
    }
    


  • Ein Lock wird aufgehoben, wenn der Kontrollfluss irgendwie den Block verlässt. Egal ob durch Exception, Return, aus eigener Kraft oder sonstwie. Sobald Dein Programm auf irgendeine Art und Weise nicht mehr innerhalb des Lock-Blocks ist, ist der Lock aufgehoben.

    Habe ich übrigens schon erwähnt, dass es egal ist, wie der Block verlassen wird? 🙂

    Dasselbe gilt für finally, sobald der zugehörige try-Block abgeschlossen wurde. Egal, ob durch Return, durch Werfen, durch Fangen, durch Fangen und Weiterwerfen oder auf natürlichem Wege.



  • Du hast vergessen zu erwähnen, dass es auch bei einem goto aus dem Block heraus funktioniert. 🙂


Anmelden zum Antworten