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.


Log in to reply