Frage zu critical sections



  • In meinem multi threat Programm wird an einer Stelle ein Unterprogramm aufgerufen, daß bedingt durch die Laufzeit teilweise falsche Daten liefert, weil mehrer Threat das Unterprogramm gleichzeitig aufrufen.

    das Unterprogramm sieht so aus:

    void Process_Data(int counter){
    :
    :
    :
    }
    

    Aufruf, gnaz klar durch:

    Process_Data(counter);
    

    Wie kann ich das komplette Unterprogramm als critical section laufen lassen, ist das überhaupt sinnvoll? Vom Ablauf meines Programmes her gesehen, wäre es unerheblich, wenn die einzelnen Threats auf dieses Unterprogramm warten müssen, da der zeitaufwendige Teil, (dies war der Grund mehrere Threat zu benutzen) an anderer Stelle geschieht und dieser Teil lediglich im promille Bereich des Threats liegt. Liege ich mit der Überlegung eine critical section zu benutzen eigentlich richtig, oder gibt es bessere/einfachere Lösungsansätze? Ich hoffe hier weis jemand Rat 🙂



  • Critical Sections werden mit der WinAPI erstellt, ich verschieb dich dort mal hin.

    Aber wenn die Methode thread-safe sein soll, warum nicht die ganze mit einer CS umspannen?

    MfG SideWinder



  • Dieser Thread wurde von Moderator/in SideWinder aus dem Forum DOS und Win32-Konsole in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • ja mach einfach den aufruf zu der funktion in eine critical section

    [critical section]
    unterprogramm()
    [/critical section]



  • WideSinder schrieb:

    ja mach einfach den aufruf zu der funktion in eine critical section

    [critical section]
    unterprogramm()
    [/critical section]

    Schön genauso hab ich mir das vorher auch schon ausgedacht, aber ich weis nicht wie ich's schreine soll? Vielleicht so:
    Irgendeine Variable "LPCRITICAL_SECTION My_CriticalSection;" definieren
    und als code das da ausführen?

    EnterCriticalSection(My_CriticalSection);
    Process_Data(counter);
    LeaveCriticalSection(My_CriticalSection);
    

    vor dem Starten des ersten Threads noch "InitializeCriticalSection" und beim beenden des letzten Threats noch "DeleteCriticalSection", darf ich mir das so vorstellen? Jo compilieren läßt sich das Ganze und dann kommt auch schon das nette Popup "Diese Anwendung wird blablabla ungültig mehrbblablablabla !oh!-> geschlossen". Ja wie gesagt ich habe keinen blassen Schimmer wie ich den Code schreiben soll. Aber auf solch eine triviale Idee wie

    [critical section]
    unterprogramm()
    [/critical section]

    bin ich auch schon gekommen, nur mit dem Umsetzen happerts eben.



  • so ungefär..

    #include <stdio.h>
    #include <windows.h>
    #include <process.h>
    #include <math.h>
    
    static int g_wichtig; 
    CRITICAL_SECTION cs;
    
    void wichtig( int a )
    {
    	EnterCriticalSection(&cs);
    	g_wichtig += a;
    	g_wichtig++;
    	LeaveCriticalSection(&cs);
    }
    
    void threadfunc_a( void *arg )
    {
    	while(1)
    		wichtig( rand() % 100 );
    }
    
    void threadfunc_b( void *arg )
    {
    	while(1)
    		wichtig( rand() % 500 );
    }
    
    int main(int argc, char* argv[])
    {
    	HANDLE handle[2];
    
    	InitializeCriticalSection(&cs);
    
    	handle[0] = (HANDLE) _beginthread( threadfunc_a, 0, NULL );
    	handle[1] = (HANDLE) _beginthread( threadfunc_b, 0, NULL );
    
    	WaitForMultipleObjects( 2, handle, TRUE, INFINITE );
    	DeleteCriticalSection(&cs);
    	return 0;
    }
    


  • Yo das sieht ja mal richtig gut aus, und laufen tut es auch schon, danke schön fdsdfs. Hab zwei Versionen compiliert eine mit dem critical section eintrag eine ohne, die ohne schmeist häufig die Daten durcheinander die andere kein einziges Mal, ich hätte da noch eine Frage, brauche ich diese Zeile unbedingt, natürlich in abgewandelter Form?

    WaitForMultipleObjects( 2, handle, TRUE, INFINITE );
    

    Ich hab zwar den Eintrag dazu in der MSDN gelesen, aber so ganz verstanden für was die Funktion gut ist, hab ich nicht.

    Und dann noch:

    InitializeCriticalSection(&cs);
    

    Führe ich das nur ein einziges mal beim Programmstart aus und

    DeleteCriticalSection(&cs);
    

    nur einaml beim Beenden des Programms? Denn in meinem Programm können die Threats, wenn sie beendet wurden auf Tastendruck erneut ausgeführt werden.



  • Einsteiger schrieb:

    InitializeCriticalSection(&cs);
    

    Führe ich das nur ein einziges mal beim Programmstart aus und

    DeleteCriticalSection(&cs);
    

    nur einaml beim Beenden des Programms?

    Ganz genau!



  • Einsteiger schrieb:

    Yo das sieht ja mal richtig gut aus, und laufen tut es auch schon, danke schön fdsdfs. Hab zwei Versionen compiliert eine mit dem critical section eintrag eine ohne, die ohne schmeist häufig die Daten durcheinander die andere kein einziges Mal, ich hätte da noch eine Frage, brauche ich diese Zeile unbedingt, natürlich in abgewandelter Form?

    WaitForMultipleObjects( 2, handle, TRUE, INFINITE );
    

    Ich hab zwar den Eintrag dazu in der MSDN gelesen, aber so ganz verstanden für was die Funktion gut ist, hab ich nicht.

    nee das brauchste ned das war nur damit main() ned gleich returned



  • In meinem multi threat Programm

    Wenn willst Du denn alles bedrohen?



  • brauche ich diese Zeile unbedingt

    Ja, die brauchst Du, da EnterCriticalSection und LeaveCriticalSection in den Threads sonst u. U. mit einem ungültigen Objekt aufgerufen werden, da dieses bereits mit DeleteCriticalSection zerstört worden sein kann.



  • Ja, aber wenn ich DeleteCriticalSection, so wie der Jochen sagt, erst beim Beenden meines Programmes ausführe, tritt dieses Problem doch gar nicht erst auf, oder?



  • Irgendwann nach der Rückkehr aus der main-function wird die CRT ExitProcess aufrufen. Dabei werden alle Threads dieses Prozesses "gewaltsam" beendet. Dies sollte an sich schon vermieden werden. Bei dem Programmbeispiel ist es allerdings notwendig, da die Sub-Threads sich hier niemals selbst beenden.

    WaitForMultipleObjects wartet auf die Beendigung der 2 Sub-Threads. Ohne dieses Abwarten wird die CriticalSection gleich nach Erzeugung der Sub-Threads zerstört. Die Sub-Threads laufen aber unabhängig vom Haupt-Thread weiter. Wird in einem Sub-Thread (vor dessen Zerstörung beim Ende des Prozesses) dann EnterCriticalSection oder LeaveCriticalSection aufgerufen, erfolgt der Aufruf mit einem ungültigen CriticalSection-Object.

    Da die Sub-Threads im Beispiel sich allerdings nicht von selbst beenden, wird ein WaitForMultipleObjects hier natürlich für ein endloses Warten sorgen.



  • Äähmmm ja, danke für die Erklärung, hab sie aber nicht so ganz verstanden. Also ich hab den Eintrag

    DeleteCriticalSection(&cs);
    

    unter

    case WM_DESTROY:
    

    eingefügt, ist das ok. Meine Threads beenden sich eigentlich alle mit ExitThread.

    Hmm, bis jetzt lief mein Proggy auch problemlos, aber man weis ja nie wo der Hund noch überall begraben liegt 🙂



  • Einsteiger schrieb:

    Meine Threads beenden sich eigentlich alle mit ExitThread.

    Hmm, bis jetzt lief mein Proggy auch problemlos, aber man weis ja nie wo der Hund noch überall begraben liegt 🙂

    Überprüfst du auch, daß sich die Threads beendet haben, bevor du dein Programm beendest? Wenn nicht, könntest du auf genau das Problem stoßen, um das es geht - irgendein Hilfsthread krallt sich zwischen dem WM_DESTROY und dem physischen Programmende die gelöschte Critical Section.


Log in to reply