Threadproblem?



  • Hallo habe mal eine Frage zu folgendem Code:

    #define NULL (void*)0
    
    typedef struct test
    {
     int test;
    } test_typ;
    
    static test_typ *pInst = NULL;
    
    void Func(test_typ *test)
    {
     pInst = test;
    
     SetIt(test->test);
    }
    
    static void SetIt(int test)
    {
     pInst->test = test;
    }
    

    Kann es hier beim Aufruf von Func(test_typ *test) aus mehereren Threads zu Problemen kommen?



  • static test_typ pInst = NULL;
    

    Das schluckt der Compiler?



  • 😃 Das sollte nur ein Beispiel sein.

    #include <string.h>
    
    static test_typ *pInst = NULL;
    


  • Anaconda55 schrieb:

    Kann es hier beim Aufruf von Func(test_typ *test) aus mehereren Threads zu Problemen kommen?

    Was sind das für Threads?



  • Es geht nur ums prinzip. Nicht um bestimmte Threads.

    Es ist doch so oder:?

    Wenn zur gleichen Zeit die Funktion Func ausgeführt wird wird der globale Zeiger auf den letzten Aufruf gebogen, sodass Funktionsaufruf 1 auf die Struktur des zweiten Funktionsaufruf schreibt!??

    Oder kann dieser Fall sowieso nie eintreten und der Code ist so sicher?



  • Anaconda55 schrieb:

    Kann es hier beim Aufruf von Func(test_typ *test) aus mehereren Threads zu Problemen kommen?

    Ja natürlich. Die Zuweisungen sind nicht unbedingt atomar und daher kann es sein, dass du nicht nur den Wert vom zweiten Aufruf in pInst stehen hast, sondern dass du sogar irgend einen falschen Wert in pInst hast. Solche Zugriffe musst du immer entsprechend absichern.



  • Das einfachste wäre in diesem Fall auf den globalen Pointer zu verzichten und SetIt die Struktur zu übergeben (SetIt(test_typ *test, int test)). Dann ist der Code sicher oder?



  • Wenn du alle Änderungen zuerst an test machst und am Schluss nur noch eine einzige Zuweisung ohne Auslesen von test zu pInst hast (atomar), wäre es sicher.

    Übrigens: (void*)0 würde ich lieber noch einmal umklammern zu ((void*)0).



  • type sans e schrieb:

    Übrigens: (void*)0 würde ich lieber noch einmal umklammern zu ((void*)0).

    Ich würde eher das eingebaute NULL empfehlen.



  • type sans e schrieb:

    Wenn du alle Änderungen zuerst an test machst und am Schluss nur noch eine einzige Zuweisung ohne Auslesen von test zu pInst hast (atomar), wäre es sicher.

    Kannst Du dazu ein Beispiel abgeben?
    Ich denke pInst brauche ich gar nicht mehr ...



  • Anaconda55 schrieb:

    Ich denke pInst brauche ich gar nicht mehr ...

    Dann lass es weg! Schreibzugriffe, die nicht stattfinden, machen selten Probleme.



  • optional einfach thread-local machen!
    (so macht es die C Standard Library mit errno)

    Beispiel MSVC:
    statt static wird "__declspec(thread)" verwendet (ohne Anführungszeichen)
    http://msdn.microsoft.com/en-us/library/6yh4a9k1.aspx

    Beispiel GCC:
    statt static wird "__thread" verwendet (auch ohne Anführungszeichen)
    http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Thread-Local.html

    Allerdings scheint MinGW gewisse Probleme mit __thread zu haben.
    Daher wäre unter Windows auch eher MSVC zu empfehlen.

    thread-local bedeutet, dass die Variable zwar statisch ist, aber jeder Thread seine eigene Variabe hat. Damit kommt es nicht zu Kollisionen.


Anmelden zum Antworten