Mehrere Threads die auf eine Speicherklasse zugreifen



  • Guten Tag,
    ich habe ein Problem und zwar würde ich gerne eine Multithreading Anwendung entwickeln, bei der alle drei Threads auf eine Klasse ImgStorage zugreifen. Das Problem ist, dass das Ausführen der Threads die Attribute meines ImgStorage-Objekts nach Lust und Laune zu ändern scheint. ```
    ... Code ...

     ... Code ... 
    ```//ImgStorage.h 
    class ImgStorage 
    {
    public:
    	ImgStorage(void);
    	~ImgStorage(void);
    private: 
    	bool testBool;
    };
    // ImgStorage.cpp
    ImgStorage::ImgStorage(void)
    {
    testBool = false;
    }
    // main.cpp
    void thread_process1(ImgStorage storageObj){
    // do smth
    }
    void thread_process2(ImgStorage storageObj){
    // do smth
    }
    
    int main(int argc, char* argv[]){
    ImgStorage imgStorageObj;
    while(true){
    		boost::thread thread1(boost::bind(thread_process1,boost::ref(imgStorageObj)));
    		boost::thread thread2(boost::bind(thread_process2,boost::ref(imgStorageObj)));
    		thread1.join();
    		thread2.join();
    }
    
    }
    

    So in etwa sieht mein Code aus. Natürlich habe ich jetzt das meiste weggelassen. Wenn ich es so ausführen würde, dann kann ich beim Debuggen in den Threadfunktionen erkennen, dass boolTest ohne, dass es überhaupt Code in den Threadfunktionen gibt geändert wird. Außerdem hat das imgStorageObj unterschiedliche Adressen in den beiden Threads.
    Wie bekomme ich es hin, dass ich wirklich nur ein imgStorageObj erschaffe und auch wirklich beide Threads auf dieses zugreifen? Hat da jemand eine Idee, vielleicht auch wie ich es alternativ lösen kann ?



  • Schreibe bitte ``` in eine Zeile über und ``` in eine Zeile unter deinen Code. Alternativ, markiere Deinen Code und klicke auf </>.



  • @henpar96 sagte in Mehrere Threads die auf eine Speicherklasse zugreifen:

    Außerdem hat das imgStorageObj unterschiedliche Adressen in den beiden Threads.

    Klar, weil thread_process1 und thread_process2 das übergebene Objekt kopieren (call by value). Daran ändert auch das boost::ref bei der Übergabe nichts.

    Ändere die thread_process-Funktionen so, dass sie eine (const) Referenz nehmen.

    Edit:
    @henpar96 sagte in Mehrere Threads die auf eine Speicherklasse zugreifen:

    Wie bekomme ich es hin, dass ich wirklich nur ein imgStorageObj erschaffe und auch wirklich beide Threads auf dieses zugreifen?

    So wie oben beschrieben sollte das dann der Falls ein.

    BTW: Ausser in Spezialfällen musst Du den Zugriff synchronisieren (die Typen/Mechanismen aus dem atomic oder mutex Header benutzen).



  • @theta Danke erst mal für die schnelle Hilfe.

    Also zum Punkt, dass sie nicht die gleichen Adressen bekommen:

    boost::reference_wrapper<ImgStorage> storageReference = boost::ref(storageObj);
    

    Wenn ich den Thread-Funktionen diesen Parameter gebe dürfe das erledigt sein oder ?

    1. Wenn ich const. Referenzen übernehme, dann kann ich die Methoden der ImgStorage Klasse nicht mehr benutzen. Wie löse ich das ? Dazu sei gesagt, dass die Threads den Inhalt vom Storage ändern dürfen. Ein Thread kümmert sich um das befüllen des Storage mit Sensorbildern, ein Thread holt die Bilder und verarbeitet den Inhalt und der letzte Thread sortiert den Storage (bearbeitete Bilder löschen, usw. )

    2. Die Synchronisation folgt noch keine Sorge 😉



  • @henpar96 sagte in Mehrere Threads die auf eine Speicherklasse zugreifen:

    Wenn ich den Thread-Funktionen diesen Parameter gebe dürfe das erledigt sein oder ?

    Eben nicht. boost::ref verhindert nur, dass innerhalb von boost::bind kopiert wird - nicht aber bei der Übergabe an die Funktion.

    Die Prozess-Funktionen müssen so angepasst werden:

    void thread_process1(ImgStorage& storageObj){}
    

    oder

    void thread_process1(const ImgStorage& storageObj){}
    

    (Bei der 2. Variante kann natürlich storageObj nicht verändert werden, was aus Threading-Sicht sehr wünschenswert wäre. Dann kann man boost::cref verwenden.)

    @henpar96 sagte in Mehrere Threads die auf eine Speicherklasse zugreifen:

    Wenn ich const. Referenzen übernehme, dann kann ich die Methoden der ImgStorage Klasse nicht mehr benutzen. Wie löse ich das ?

    Wenn Du sie nicht mehr benutzen kannst, dann sind die Methoden von ImgStorage nicht const - wenn das erforderlich ist, dann ist das so. Lösen kannst Du das, indem Du eben keine const& übergibst, sondern nur eine &.

    @henpar96 sagte in Mehrere Threads die auf eine Speicherklasse zugreifen:

    Die Synchronisation folgt noch keine Sorge

    Naja, das ist ein bisschen wie mit den Vorzeichen bei den Musiknoten: Es funktioniert nicht, sie zuerst einfach mal wegzulassen.



  • C++ hat seit sieben Jahren Threads und Lambdas. Warum verwendest du boost::thread und boost::bind?

    bei der alle drei Threads auf eine Klasse ImgStorage zugreifen

    Das ist häufig der Grund dafür, das ein Programm langsamer läuft als mit einem Thread.



  • @manni66 Der Grund fürs Multithreading ist in diesem Fall keine Performance-Sache. Ich programmiere hier für einen Robotorarm an dem ein Sensor angebaut ist. Wichtig ist hierbei, dass die Bilder durchgehend aufgenommen und gespeichert werden, da sich der Arm bewegt. Wie lange die Verarbeitung der Bilder braucht ist nebensächlich. Bei einem Thread müsste die Kamera immer auf die Verarbeitung eines Bildes warten bevor neue Bilder gespeichert werden können.