Frage Mutex / lock verwendung?



  • Ich habe folgende klassen:

    Class Mutex{
        CRITICAL_SECTION _critSection;
    public:
    
        Mutex () { InitializeCriticalSection (& _critSection); }
        ~Mutex () { DeleteCriticalSection (& _critSection); }
        void Acquire(){ EnterCriticalSection (& _critSection); }
        void Release(){ LeaveCriticalSection (& _critSection); }
    };
    
    class Lock {
    
    private:
        Mutex & _mutex;
    public:
    
        // Acquire the state of the semaphore
        Lock (Mutex &mutex): _mutex(mutex){  _mutex.Acquire();   }
    
        // Release the state of the semaphore
        ~Lock (){ _mutex.Release(); }
    
    };
    

    Wenn nich nun zwei threads habe, gibt es ja jetzt zwei möglichkeiten der ressourcen syncronisation: (Beide haben eine Referenz auf das gleiche Mutex objekt objMutex)

    A: code jeweils in den Threads:

    {
    objMutex.Acquire();
    
    //gemeinsam genutzer ressource verwenden
    
    objMutex.Release();
    }
    

    B: code jeweils in den Threads:

    {
    Lock objLock(objMutex);
    
    //gemeinsam genutzer ressource verwenden
    }
    

    in B wird die ressoruce wieder freigeben wenn das Lock objekt zerstört wird. in A muss ich die sperrung und freigabe selbst machen.

    was gibt hier jeweils für vor und nachteile?



  • gibt keine vor- und nachteile in dem sinne. die beiden methoden sind für unterschiedliche anwendungszwecke gedacht. es kann durchaus situationen geben, in denen man den lock über die grenzen eines scopes hinaus aufrecht erhalten will.

    wenn man sowas macht, muss man natürlich besonders darauf achten, dass die sperre garantiert irgendwann wieder aufgehoben wird. daher ist die "automatische" aufhebung des locks bei verlassen des scopes normalerweise zu bevorzugen, weil sie schlicht für weniger programmierfehler sorgt 😉



  • der vorteil bei diesem szenario, bei B wird die ressoure garantiert wieder frei gelassen...

    A:
    {

    objMutex.Acquire();
    
    //do something
    
    return;
    
    objMutex.Release();
    }
    

    B:

    {
    Lock objLock(objMutex);
    
    //do something
    
    return;
    
    }
    


  • Genau, oder es könnte irgendwo zwischen Aquire und Release eine Exception geworfen werden (auch von weiter unten). Also ich würde auch sagen, dass die Lock-Methode besser ist, wenn man einen normalen Scope-Lock braucht.



  • naja würde aber da eine asserstion austreten, würde auch der Lock versagen oder?



  • BorisDieKlinge schrieb:

    der vorteil bei diesem szenario, bei B wird die ressoure garantiert wieder frei gelassen......

    Stimmt natürlich ... ist aber relevanter, wenn Exceptions fliegen, weil man ein "versehentliches return" noch relativ einfach findet/vermeiden kann. Wenn aber irgendeine genutzte Funktion (am Besten von "fremd" programmiert, nicht als Source verfügbar und "versteckt" wie ein Konstruktor oder ein operator) eine Exception wirft (am Besten undokumentiert), hat man echte Schwierigkeiten.

    Ehrlich gesgt: Ich sehe gar keinen Vorteil von Variante A ggü. Variante B.

    Gruß,

    Simon2.



  • BorisDieKlinge schrieb:

    naja würde aber da eine asserstion austreten, würde auch der Lock versagen oder?

    😕
    Du sprichst mir unbekannte Sprachen ....
    Warum sollte ein "Lock versagen", wenn eine Exception fliegt ? Und was haben "assertions" damit zu tun ? ...

    Gruß,

    Simon2.



  • sorry ich mein damit, wenn eine unbehandelter fehler ohne exzeptions da auftritt wird das lock objekt nicht zerstört.. man muss definitf mit dem try /catch gedöns arbeiten



  • BorisDieKlinge schrieb:

    sorry ich mein damit, wenn eine unbehandelter fehler ohne exzeptions da auftritt wird das lock objekt nicht zerstört.. man muss definitf mit dem try /catch gedöns arbeiten

    Wenn ein unbehandelter Fehler (➡ unbehandelte Exception oder Assertion) fliegt, ist Dein Programm sowieso zuende. Da macht auch ein try/catch nichts mehr. In allen anderen Fällen wird der Destruktor beim Verlassen des Scope aufgerufen.



  • BorisDieKlinge schrieb:

    sorry ich mein damit, wenn eine unbehandelter fehler ohne exzeptions da auftritt wird das lock objekt nicht zerstört.. man muss definitf mit dem try /catch gedöns arbeiten

    OK, jetzt verstehe ich wenigstens, welchen Denkfehler Du gemacht hast. 😉
    Wie Lord schon gesagt hat: Das geht schon so.

    Gruß,

    Simon2.


  • Mod

    Was soll das überhaupt sein: ein unbehandelter Fehler?



  • Nur mal am Rande: In der ATL/MFC werden deshalb die Objekte (Mutexe, Critical Sections etc.) in eigenen Klassen gehalten, die nichts mit der Verwendung, also dem Lock zu tun haben. Dafür gibt es eine universelle CSingleLock/CMultiLock Klasse die den Lock selbst verwaltet.
    RAII ist dadurch gewährleistet!


Log in to reply