Variablenzugriff Threadsafe.



  • Optimizer schrieb:

    Das Problem ist noch weitergehend, für CPUs mit mehr als einem Hardware-Thread entstehen auch bei einzelnen Befehlen schon Inkosistenzen zwischen den verschiedenen Caches. Man kommt also nicht daran vorbei, den Cache nach dem Schreiben zu flushen und in anderen Caches diese Line neu einzulesen. Dies geschieht bei volatile-Variablen automatisch und ist u.U. sauteuer.

    Okay. Dann einen Mutex, volatile oder kein volatie und hoffen, das es klappt. Ich will nur eine Schleife, die in einem Thread abläuft, aus dem anderen beenden.

    Optimizer schrieb:

    Auch spiegeln die ASM-Befehle nicht die reale CPU-Architektur wieder, die werden erst wieder in mehrere Mikrobefehle umgewandelt und auch intern parallelisiert ausgeführt. Vielleicht reicht allein das schon, um Probleme zu machen.

    Das war auch meine Überlegung. Es könnte ja sein, dass ein long byteweise zugewiesen wird, oder so...



  • net schrieb:

    ProgChild schrieb:

    Hab irgendwo gelesen, dass der lesende Thread inkonsistente Daten lesen könnte, wenn ein lese und ein schreib Thread existieren. Ist das hier auch der Fall?

    wenn für's lesen oder schreiben mehr als eine asm-instruction nötig sind, dann brauchste 'nen lock, sonst sollte das ohne gehen...

    nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)



  • rüdiger schrieb:

    nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)

    Was passiert denn im schlimmsten Fall auf einem Multiprozessor System? Wäre ja nicht schlimm, wenn der Thread erst etwas später abgebrochen wird, wenn die Chaches Synchronisiert werden.



  • Es ist klar, dass du Mutexe oder andere Synchronisationsmethoden verwenden musst.

    Das folgende Programm sieht von außen ok aus (es sei denn man ist in Multithreading geschult):

    extern "C" {
    #include <pthread.h>
    #include <unistd.h>
    }
    
    #include <iostream>
    
    int flag = 0;
    
    void * th(void *) {
    
            sleep(5);
            flag = 1;
            std::cout << "Counter is now " << flag << std::endl;
            return NULL;
    }
    
    int main() {
    
            pthread_t pid;
            pthread_create(&pid, NULL, th, NULL);
    
            unsigned int counter = 0;
            while (flag == 0) {
                    ++counter;
            }
            pthread_join(pid, NULL);
    
            std::cout << "Counter: " << counter << std::endl;
    }
    

    Übersetzt mit

    g++ -Wall -W -pedantic -pthread -O2 thread.C
    

    läuft das Programm in eine Endlosschleife.

    volatile hilft in diesem Beispiel, ist aber keine allgemeine Lösung. Siehe

    http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf



  • ProgChild schrieb:

    rüdiger schrieb:

    nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)

    Was passiert denn im schlimmsten Fall auf einem Multiprozessor System? Wäre ja nicht schlimm, wenn der Thread erst etwas später abgebrochen wird, wenn die Chaches Synchronisiert werden.

    Verallgemeinert gesagt, sehen verschiedene Threads unterschiedliche Werte, weil jeder seinen eigenen Cache hat. Schreiboperationen sieht eine ganze Zeit lang nur der schreibende Thread selber. Das ist katastrophal.



  • Wobei das auch stark von der Architektur des Systems abhängig ist.



  • Optimizer schrieb:

    Auch spiegeln die ASM-Befehle nicht die reale CPU-Architektur wieder, die werden erst wieder in mehrere Mikrobefehle umgewandelt und auch intern parallelisiert ausgeführt.

    glaub' nicht. auch wenn's micro'code' heisst, so isses doch meistens so schnell wie ein elektron braucht um in's silizium einzudringen, damit hinten ein anderes rausfällt 😉

    rüdiger schrieb:

    net schrieb:

    ProgChild schrieb:

    Hab irgendwo gelesen, dass der lesende Thread inkonsistente Daten lesen könnte, wenn ein lese und ein schreib Thread existieren. Ist das hier auch der Fall?

    wenn für's lesen oder schreiben mehr als eine asm-instruction nötig sind, dann brauchste 'nen lock, sonst sollte das ohne gehen...

    nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)

    jo, beim mehrprozzi haste das problem der verschachtelten bus-nutzung, da kann einer schon die speicherzelle verändert haben, während der andere erst den befehl decodiert hat. aber naja, ich meinte mit meinem posting das zeitscheiben-multitasking mit nur einer cpu. dabei ist ja ein asm-befehl nicht unterbrechbar...



  • net schrieb:

    jo, beim mehrprozzi haste das problem der verschachtelten bus-nutzung, da kann einer schon die speicherzelle verändert haben, während der andere erst den befehl decodiert hat. aber naja, ich meinte mit meinem posting das zeitscheiben-multitasking mit nur einer cpu. dabei ist ja ein asm-befehl nicht unterbrechbar...

    Okay war jetzt das Resultat, dass ich volatile und Mutexe brauche, um sowas vernünftig zu realisieren, aber eig. volatile in der geg. Situation ausreicht?



  • ProgChild schrieb:

    net schrieb:

    jo, beim mehrprozzi haste das problem der verschachtelten bus-nutzung, da kann einer schon die speicherzelle verändert haben, während der andere erst den befehl decodiert hat. aber naja, ich meinte mit meinem posting das zeitscheiben-multitasking mit nur einer cpu. dabei ist ja ein asm-befehl nicht unterbrechbar...

    Okay war jetzt das Resultat, dass ich volatile und Mutexe brauche, um sowas vernünftig zu realisieren, aber eig. volatile in der geg. Situation ausreicht?

    Du brauchst nur Mutexe. volatile ist nicht nötig. volatile alleine ist falsch.



  • wenn du windoofs hast, dann nimm dafür die 'InterlockedXXX' funktionen. die gehen auch bei mehreren prozessoren...



  • Ponto schrieb:

    Du brauchst nur Mutexe. volatile ist nicht nötig. volatile alleine ist falsch.

    Warum? Solang die Synchronisation nur in eine Richtung geht und die Variable nur einmal dazu verwendet wird sehe ich kein Problem mit volatile.



  • net schrieb:

    wenn du windoofs hast, dann nimm dafür die 'InterlockedXXX' funktionen. die gehen auch bei mehreren prozessoren...

    Nein, kein Windoof. Warum ich überhaupt darauf komme. Hab mir den Quelltext von XMMS angeschaut und da scheint es komplett ohne Mutex und ihne volatile gemacht worden zu sein...

    Naja, ich werd dann wohl einfach zu sicherheit Mutexe setzten.

    Danke an Alle.



  • Jester schrieb:

    Ponto schrieb:

    Du brauchst nur Mutexe. volatile ist nicht nötig. volatile alleine ist falsch.

    Warum? Solang die Synchronisation nur in eine Richtung geht und die Variable nur einmal dazu verwendet wird sehe ich kein Problem mit volatile.

    Du hast doch selbst geschrieben, dass es stark systemabhängig sei.

    Zunächst gibt es das Totschlagargument, dass C++ selbst kein Multithreading kennt und keine volatile Semantik für Multithreadingprogramme spezifiziert wurde. Aber soweit ich weiss haben auch Systeme mit Multithreading wie POSIX 1003.1 haben keine Semantik für volatile über Threads hinweg spezifiziert.

    Dann kann man sich immer darauf zurückziehen, dass es Systeme geben kann in denen das nicht funktioniert. Nehmen wir mal ein System an, bei dem jedes Lesen aus dem Speicher von einem Schreiben mit dem gelesenen Wert gefolgt werden muss. Was passiert nun wenn der eine Thread den Wert ändert und der andere den gleichzeitig liest?

    Auf so einem System kann die Singlethreadingsemantik von C++ problemlos implementiert werden.



  • Jo okay, ich ging jetzt von irgendner üblichen Plattform aus, was man so zu Hause hat. Also sowas wie nen AMD mit einem/mehreren Kernen oder auch nen Dualpentium oder sowas. Da sollte volatile genügen.

    Auf ner beliebigen Plattform kann man natürlich nicht viel mehr sagen, als daß man geeignet synchronisieren muß. 😉


Anmelden zum Antworten