Verhalten von Boost-Threads unter MS VS 2010



  • Hallo,

    ich habe mal foldendes Programm aus einem alten iX-Artikel eingegeben. Das Programm läuft auch problemlos. Nur ich verstehe das Verhalten nicht.

    #include <iostream>
    #include <boost\thread.hpp>
    
    int counter;
    const int NCOUNT = 100;
    boost::mutex incrementMutex;
    
    void increment(const int ncount)
    {
    	for (int i(0); i < ncount; i++)
    	{
    		boost::lock_guard<boost::mutex> lock(incrementMutex);
    		counter++;
    		std::cout << counter << std::endl;
    	}
    }
    
    void decrement(const int ncount)
    {
    	for (int i(0); i < ncount; i++)
    	{
    		boost::lock_guard<boost::mutex> lock(incrementMutex);
    		counter--;
    		std::cout << counter << std::endl;
    	}
    }
    
    int main(int argc, char* argv[])
    {
    	counter = 0;
    
    	boost::thread a(std::bind(increment, NCOUNT));
    	boost::thread b(std::bind(decrement, NCOUNT));
    
    	a.join();
    	b.join();
    
    	std::cin.get();
    
    	return 0;
    }
    

    Wenn ich das Programm starte zählt das Programm erst runter und dann rauf, oder auch andersrum. Ich hätte erwartet das sich der Wert der Variable counter kaum erhöht, weil beide Threads ungefähr gleichviel CPU-Zeit bekommen.

    Etwas ratlos...

    Ich verwende MS VS 2010 und die Boost-Library 1.54.0.



  • Es ist nicht garantiert in welcher Reihenfolge die Threads Prozessorzeit bekommen (das hast du ja selbst festgestellt). Und vielleicht hält das Betriebssystem es für richtig, dass erst der erste Thread alle Zeit bekommt und danach der zweite bei dir...

    Zumal das was du da machst, ja auch noch keine Zeit kostet. 100 Addition ist lächerlich, der Prozessor geht da nebenbei noch shoppen...



  • Danke für die Info.

    Skym0sh0 schrieb:

    Es ist nicht garantiert in welcher Reihenfolge die Threads Prozessorzeit bekommen (das hast du ja selbst festgestellt). Und vielleicht hält das Betriebssystem es für richtig, dass erst der erste Thread alle Zeit bekommt und danach der zweite bei dir...

    Zumal das was du da machst, ja auch noch keine Zeit kostet. 100 Addition ist lächerlich, der Prozessor geht da nebenbei noch shoppen...

    Es ist ja auch nur ein Beispiel und manchmal sieht man die Parallelität der Threads in der Ausgabe. Hatte nur ein deutlicheres Ergebnis erwartet.

    Gibt es in Boost bzw. im C++11 Standard ausser die Prioritaet Steuermechanismen die Verteilung zu steuern?



  • WiederMalamRaetseln schrieb:

    Gibt es in Boost bzw. im C++11 Standard ausser die Prioritaet Steuermechanismen die Verteilung zu steuern?

    .. bedingt. Versuche mal:

    #include <iostream>
    #include <boost\thread.hpp>
    
    void increment( boost::mutex& incrementMutex, int& counter, const int ncount)
    {
        for (int i(0); i < ncount; ++i )
        {
            {
            boost::lock_guard<boost::mutex> lock(incrementMutex);
            counter++;
            std::cout << "+ " << counter << std::endl;
            }
            boost::this_thread::yield();
        }
    }
    
    void decrement( boost::mutex& incrementMutex, int& counter, const int ncount)
    {
        for (int i(0); i < ncount; ++i )
        {
            {
            boost::lock_guard<boost::mutex> lock(incrementMutex);
            counter--;
            std::cout << "- " << counter << std::endl;
            }
            boost::this_thread::yield();
        }
    }
    
    int main(int argc, char* argv[])
    {
        int counter = 0;
        const int NCOUNT = 100;
        boost::mutex incrementMutex;
    
        boost::thread a(std::bind(increment, boost::ref(incrementMutex), boost::ref(counter), NCOUNT));
        boost::thread b(std::bind(decrement, boost::ref(incrementMutex), boost::ref(counter), NCOUNT));
    
        a.join();
        b.join();
    
        std::cin.get();
    
        return 0;
    }
    


  • Hallo Werner,

    jetzt ist das Verhalten so wie ich es erwartet habe. Der Counter schwankt je nach Programmstart zwichen -20 und 20, meistens aber nur zwischen -10 bis 10.

    Mit dem yield wird der Thread explizit freigegeben. Oder?

    Warum übergibst du Referenzen statt wie im Beispiel der direkte Zugriff auf die globalen Variablen?



  • zu yield siehe http://www.boost.org/doc/libs/1_55_0/doc/html/thread/thread_management.html#thread.thread_management.this_thread.yield

    Effects:
    Gives up the remainder of the current thread's time slice, to allow other threads to run.

    WiederMalamRaetseln schrieb:

    Warum übergibst du Referenzen statt wie im Beispiel der direkte Zugriff auf die globalen Variablen?

    zum einen wollte ich sicher stellen, dass sich mit dem globalen Mutex nichts ändert und zum anderen ..

    .. globale Variablen sind: 👎


Anmelden zum Antworten