CSemaphore



  • Hallo.

    Bin gerade dabei Threads zu synchronisieren. Ein Thread wird gestartet. Dieser ruft nun eine Funktion auf, die wiederum eine weitere Funktion (Funktion 😎 sperren soll. Funktion B darf erst ausgeführt werden wenn kein Thread am laufen ist.

    Dies führe ich mit einer Semaphore durch. Die Threads rufen m_semaphore.Lock auf und am Ende m_semaphore.UnLock()

    Die Semaphore habe ich wie folgt initialisiert: CSemaphore m_semaphore(5,5);

    In der Funktion B Warte ich mit CSingleLock(&m_semaphaphore). Doch hier wartet nun mein Programm nicht sondern läuft durch. Wieso



  • Hallo nochmals einfacher erklärt.

    Ich will mehrere Threads starten. Dies Threads benötigen ein Objekt. Damit dises Objekt nun nicht gelöscht wird, muss die Funktion die das Objekt löscht blockiert werden bis alle Threads beendet sind. Wenn die Funktion ausgeführt wird, die das Objekt löscht, muss ein neuer Thread warten bis die Löschfunktion beendet ist. Der Thread erzeugt das Objekt danach neu.

    Vieleicht war das mit der CSemaphore auch der falsche Ansatz. Hoffe ihr könnt mir weiter helfen.


  • Mod

    Da genügt es doch den Zugriff auf dei Variable mt einer CCriticalSection absichern.



  • CritialSection erlaubt es doch nur ein Prozess zu einer Zeit. Bei mir ist das doch aber so dass mehrere Prozesse auf das Objekt gleichzeitig zugreifen dürfen. Nur löschen darf man es nur wenn alle anderen beendet sind.



  • tanztderbär schrieb:

    CritialSection erlaubt es doch nur ein Prozess zu einer Zeit. Bei mir ist das doch aber so dass mehrere Prozesse auf das Objekt gleichzeitig zugreifen dürfen. Nur löschen darf man es nur wenn alle anderen beendet sind.

    Was meinst du denn mit Prozessen? Mehrere Threads sind keine Prozesse und so wie du das oben geschrieben hast gehts nur darum, dass es einen GUI-Thread und mehrere Worker-Threads gibt, die irgendwie zu synchronisieren sind. Und da reicht ne CriticalSection, so wie Martin das geschrieben hat. Die lässt nur einen Thread zugreifen...
    Die Frage, ob noch Threads laufen würde ich über deren Handle m_pThread machen und erst dann die Funktion killen, wenn alle Threads returniert sind.
    Ansonsten hast du dich falsch ausgedrückt oder wir haben das falsch verstanden...



  • Ok vieleicht falsch ausgedrückt. Also keine Prozesse sondern mehrere Threads. Es dürfen mehrere Threads auf ein Objekt zugreifen. Allerdings darf der GUI Thread nur das Objekt löschen wenn alle anderen treads das objekt freigegeben haben. Diese müssen nicht beendet sein.


  • Mod

    Wenn die anderen nur Lesen und einer nur schreibt kannst Du zu einer Multiple-Reader Single-Writer Klasse greifen.

    Oder Du arbeitest einfach mit einem Intelligenten Zeiger (Referenzzählung).



  • Oder Du arbeitest einfach mit einem Intelligenten Zeiger (Referenzzählung).

    Genau so was und das dachte ich das löse ich mit einer Semaphore. Nur ich weiß nicht genau wie?



  • Ich habe da noch einen anderen Vorschlag:
    Wenn sich mehrere Threads eine Ressource, z.B. eine Variable oder Dateizugriff teilen müssen, dann kann der konkurrierende Zugriff auf über einen Mutex des Windows-API gesichert werden.

    Dazu muss zuerst ein Handle deklariert werden.
    Jeder Thread der den Zugriff auf die Ressource durchführen möchte ruft die GetMutex-Funktion auf. Wenn die Funktion mit true beendet wird, so darf der Thread auf die Ressource zugreifen. Ist die Ressource bereits zuvor durch einen anderen Thread mit GetMutex erfolgreich belegt worden, so bleibt der Thread in der Funktion GetMutex stecken und wartet bis zum Timeout (MUTEX_TIMEOUT) ob die Ressource frei wird. Wird sie allerdings nicht innerhalb dieser Timeoutzeit frei, bekommt man bei GetMutex ein false zurück, kann etwas unternehmen und ggfs. wieder GetMutex aufrufen. Wenn ein Thread mit dem Zugriff auf die Ressource fertig ist, so muss sie unbedingt RelMutex()
    aufrufen, um die Ressource für die anderen Threads freizugeben. Falls gerade ein anderer Thread in der GetMutex-Funktion wartet, so wird er vom Betriebssystem als nächster auf die Ressource freigegeben, d.h. er bekommt den Mutex.

    Im meinem Beispiel ist das ganze nicht als Klasse implementiert, sondern als globale Funktionen. Die Funktion InitMutex() muss nicht aufgerufen werden, da das automatisch beim ersten GetMutext() passiert.

    #define MUTEX_TIMEOUT 60000
    
    HANDLE hMutex=0;
    void InitMutex()
    {
    	hMutex = CreateMutex(0,0,"Name der Ressorce");  
    
    	if(!hMutex) QuitAbbruch(..........);
    }
    
    bool GetMutex()
    {
    	if(!hMutex) InitMutex();
    
    	if(!WaitForSingleObject(hMutex,MUTEX_TIMEOUT)) return 1;
    	else                                           return 0;
    }
    
    void RelMutex()
    {
    	if(hMutex) ReleaseMutex(hMutex);
    }
    

    Dieses Verfahren habe ich bereits in mehreren großen Projekten verwendet und bin damit sehr zufrieden.

    Viele Grüße
    JoyPaD



  • Hallo. Ok nochmal. Alle Threads dürfen gleichzeitig auf das Objekt zugreifen. Da brauche ich keinen mechanismus dafür. Brauche eigentlich nur einen Counter der die Zugriffe auf das Objekt zählt und nur wenn der Counter = 0 ist darf das Objekt gelöscht werden.

    Dafür bruche ich meiner Meinung nach eine Semaphore. Nur ich weiß nicht wie anwenden. Kann mir dazu niemand konkrett helfen?



  • Wenn du nur mit zählen willst, ob auf das Objekt zugegriffen wird, reicht doch ein integer...
    Oder geh ich jetzt all zu blauäugig drauf los?



  • ... da wäre ich vorsichtig. ggfs. wird der zugriff durch das Multithreading zerhackt und der Integer ist nicht mehr konsistent.


  • Mod

    JoYpaD schrieb:

    ... da wäre ich vorsichtig. ggfs. wird der zugriff durch das Multithreading zerhackt und der Integer ist nicht mehr konsistent.

    Der Zugriff auf aligned Integer ist IMHO auf allen Rechnern atomar und wird nicht durch einen context switch eines Threads zerhackt.



  • Es können aber Probleme durch re-ordering auftreten.
    Also mindestens InterlockedXX benutzen.
    Simon



  • Achso. Und mit einer Semaphore läst sich das nicht lösen?



  • Oder Du arbeitest einfach mit einem Intelligenten Zeiger (Referenzzählung).

    Wenn mir noch jemand erklären würde wie das funktioniert wäre ich glücklich 🙂



  • In der Funktion B Warte ich mit CSingleLock(&m_semaphaphore). Doch hier wartet nun mein Programm nicht sondern läuft durch. Wieso

    Könnte man mir eine einfache Antwort geben. Auf genau diese Frage!


  • Mod

    Weil es evtl. der selbe Thread ist?



  • Wenn ich die MSDN-Doku eben richtig überflogen habe, dann musst Du in der Lösch-Methode so darauf warten, dass alle anderen Threads draußen sind:

    CSingleLock singleLock(&m_CritSection);
    singleLock.Lock();  // Attempt to lock the shared resource
    if (singleLock.IsLocked())  // Resource has been locked
    {
    //...use the shared resource...
    
    // Now that we are finished, 
    // unlock the resource for others.
    singleLock.Unlock();
    }
    

  • Mod

    Warum verwendest Du keine Smart Pointer?

    Der Main-Thread erzeugt die Daten und übergibt die Smart-Pointer an die Threads.
    Wenn die lette Referenz weg ist, zerstört sich das Objekt von selbst.


Log in to reply