Thread problem



  • kein Thema...

    Wenn du keinen Mutex verwendest, sollte die Variable volatile sein um zu garantieren, dass der alte Wert im anderen Thread nicht gecached ist.

    Lass mal folgendes kompilerierfähiges(!!! 🙂 ) Programm laufen:

    #include <iostream>
    #include <boost/thread.hpp>
    #include <boost/ref.hpp>
    
    class FU : private boost::noncopyable{ 
    public:
    	FU() /*: FW()*/{ 
    
    		FU_Worker_Thread=new boost::thread(boost::bind(&FU_Worker::_Progress_FU_Worker,boost::ref(FW))); 
    	} 
    
    	class FU_Worker : private boost::noncopyable
    	{
    	private:
    		FU_Worker(const FU_Worker&){}
    	public: 
    		FU_Worker(){FU_Worker_Thread_run=true;} 
    		~FU_Worker(){} 
    
    		/// Das ist der Thread 
    		void _Progress_FU_Worker() 
    		{ 
    			while(true) 
    			{
    				if(FU_Worker_Thread_run)
    					std::cout << "Worker thread " << "yes " << this << std::endl;
    				else
    					std::cout << "Worker thread " << "no " << this << std::endl;
    			} 
    		} 
    
    		volatile bool FU_Worker_Thread_run; 
    	}; 
    
    	FU_Worker FW; 
    	boost::thread* FU_Worker_Thread; 
    
    	void toggle(){
    		if(FW.FU_Worker_Thread_run){
    			std::cout << "main thread " << "yes -> no" << &(this->FW) << std::endl;
    			FW.FU_Worker_Thread_run = false;
    		}
    		else{
    			std::cout << "main thread " << "no -> yes" << &(this->FW) << std::endl;
    			FW.FU_Worker_Thread_run = true;
    		}
    	}; 
    
    };
    
    int main(){
    	FU* fu = new FU();
    	while(true) 
    	{ 
    		fu->toggle();
    	} 
    }
    

    Ändern sich bei dir die Werte im Worker-Thread?
    Also es bei mir sieht es ziemlich durcheinander aus wegen der Kontextwechsel, aber die Werte im Worker verändern sich.

    Wenn ja, poste mal ein kompilierfähiges Programm, das bei dir nicht funktioniert.

    Also die Memory-Leaks müssen natürlich noch raus...
    Wo ist eigentlich der Singleton hin? ^^



  • XSpille schrieb:

    .

    Wenn du keinen Mutex verwendest, sollte die Variable volatile sein um zu garantieren, dass der alte Wert im anderen Thread nicht gecached ist.

    volatile hat mit Threads nichts zu tun. Microsoft unterstützt dies mittlerweile, weil der Irrglaube so verbreitet ist, aber portabel ist es nicht.



  • Hi,

    der singelton ist in der Vereinfachung verschwunden =)...
    Schaus mir gerade mal durch.

    Volatile habe ich eigentlisch schonmal versucht. ...
    In C# geht das, aber bei C++ hab ich eigentlich nie nen Unterschied feststellen könne.
    Werds nochmal versuchen.

    Ich möchte das ganze später einfach in ne DLL / so packen.
    Und da brauch ich ne Factory function, und die Instanzen kommen im meinen
    Einfachton =)....

    So werd mal schauen was er bei mir so sagt.
    Welche Compiler hast du ??
    Ich hab i686-pc-linux-gnu-4.4.5

    EDIT: Ich mutexe schon, aber mich interessiert ja wiso dei boolsche variable zwei unterschiedliche Addressen hat, wenn ich sie auf dem stack anlege.



  • manni66 schrieb:

    XSpille schrieb:

    .

    Wenn du keinen Mutex verwendest, sollte die Variable volatile sein um zu garantieren, dass der alte Wert im anderen Thread nicht gecached ist.

    volatile hat mit Threads nichts zu tun. Microsoft unterstützt dies mittlerweile, weil der Irrglaube so verbreitet ist, aber portabel ist es nicht.

    Danke für die Info...
    Aber volatile garantiert doch, dass das Caching der Variable verhindert wird, oder? Und genau das muss/sollte doch in diesem Fall gewährleistet sein, oder?

    Wikipedia sagt: http://de.wikipedia.org/wiki/Volatile_(Informatik)

    In C und C++ wird durch diesen Typqualifikator spezifiziert, dass sich der Wert der Variablen außerhalb des aktuellen Programmkontextes ändern kann

    Und ein anderer Thread ist doch ein Verändern außerhalb des aktuellen Programmkontest, oder?

    (Ich bin jetzt einfach naiv davon ausgegangen, dass diese Info bei Wikipedia korrekt ist 🙄 )



  • AlexanderKiebler schrieb:

    Welche Compiler hast du ??

    Ich verwende Mac OS X:
    g++ (GCC) 4.6.1 20110325 (prerelease)



  • Genau die überlegung ist bei mir auch angestanden.
    Ne zuweisung verhindern, damit der Wert abgefragt wird.

    Bei mir gehts gerade sowohl mit, als auch ohne volatile.

    EDIT: Soweit ich weiß sind die Compiler mit boost noch nicht getestet oder ??



  • XSpille schrieb:

    Und ein anderer Thread ist doch ein Verändern außerhalb des aktuellen Programmkontest, oder?

    Nein, C++ wird erst im kommenden Standard C++11 Threads kennen, daher bezieht sich das auf Signalhandler u.ä.. Der englische Wikieintrag ist da viel ausführlicher.

    Hier wird volatile eigentlich ganz gut beschrieben: http://drdobbs.com/high-performance-computing/212701484.
    Auch die vielen anderen Artikel von Herb Sutter zur Threadthematik sind lesenswert.



  • XSpille schrieb:

    Aber volatile garantiert doch, dass das Caching der Variable verhindert wird, oder?

    Ja, das schon.

    Und genau das muss/sollte doch in diesem Fall gewährleistet sein, oder?

    Das ist notwendig, aber nicht ausreichend.
    Es fehlt nämlich noch irgendwer, der dir eine Garantie über das Speichermodell im Zusammenhang mit Multithreading gibt.
    Und das tut der C++ (03) Standard nicht.

    Konkret kann das heissen: es könnten Memory-Barriers nötig sein, um die Sichtbarkeit von Änderungen zu garantieren. Und es kann sein, dass Reads und/oder Writes der Variable nicht Atomic sind. Das wäre u.U. auch doof.
    Uswusf.

    Multithreading ist vom C++ 03 Standard einfach nicht abgedeckt, und daher kann volatile auch keine allgemein gültige Verwendung im Zusammenhang mit Threads haben.

    ----

    MSVC garantiert dass volatile das tut, was es auch in Java oder C# tut. Andere Compiler garantieren das nicht.



  • hustbaer schrieb:

    MSVC garantiert dass volatile das tut, was es auch in Java oder C# tut. Andere Compiler garantieren das nicht.

    Heißt, in MSVC ist bei einer volatilen Variable keine Synchronisation durch Mutexes o.ä. mehr erforderlich (So ist es doch in Java, oder?) ?



  • manni66 schrieb:

    volatile hat mit Threads nichts zu tun. Microsoft unterstützt dies mittlerweile, weil der Irrglaube so verbreitet ist, aber portabel ist es nicht.

    Microsoft unterstützt es, weil es praktisch ist ein definiertes Speichermodell zu haben.



  • 314159265358979 schrieb:

    hustbaer schrieb:

    MSVC garantiert dass volatile das tut, was es auch in Java oder C# tut. Andere Compiler garantieren das nicht.

    Heißt, in MSVC ist bei einer volatilen Variable keine Synchronisation durch Mutexes o.ä. mehr erforderlich (So ist es doch in Java, oder?) ?

    Ab MSVC 2005 haben Lesezugriffe mit volatile "acquire" Semantik, und Schreibzugriffe "release" Semantik.

    http://msdn.microsoft.com/en-us/library/12a04hfd(v=vs.80).aspx

    Auf x86 und x64 Plattformen sind (unabhängig vom Compiler) Zugriffe auf Variablen mit bis zu 8 Byte "atomic", wenn die Adresse passend aligned ist (=die Variable muss vollständig innerhalb einer Cache-Line liegen), WENN der Zugriff mit einer einzigen Instruction passiert.

    MSVC erzeugt passenden Code (Quelle kann ich dir aber keinen nennen), d.h. mit MSVC sind solche Zugriffe dann "atomic" UND "acquire" bzw. "release".

    Und wenn man an den Defaults nichts ändert, tut man sich auch ziemlich schwer, Variablen zu erzeugen die nicht passend aligned wären.

    D.h. mit MSVC kann man "double checked locking" korrekt implementieren, Spin-Locks mit einem einfachen "m_lock_var = 0" freigeben etc.



  • Danke euch für die Ausführungen zu volatile...

    Inzwischen erinnere ich mich sogar, es gewusst zu haben 🤡



  • *ggg*


Anmelden zum Antworten