Die naheliegendste Art, das undefinierte Verhalten des Artikels Sukzessive Optimierung in Wohlgefallen aufzulösen, sind Locks.
Locks
Sowohl der thread1 als auch der thread2 verwenden den gleichen Mutex, den sie jeweils in einen std::lock_guard verpacken.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <iostream> #include <mutex> #include <thread> int x= 0; int y= 0; std::mutex mut; void writing(){ std::lock_guard<std::mutex> guard(mut); x= 2000; y= 11; } void reading(){ std::lock_guard<std::mutex> guard(mut); std::cout << "y: " << y << " "; std::cout << "x: " << x << std::endl; } int main(){ std::thread thread1(writing); std::thread thread2(reading); thread1.join(); thread2.join(); }; |
Das Programmverhalten ist wohldefiniert. Entweder kommt thread1 oder thread2 zuerst zum Zuge. Abhängig davon sind beide oder keiner der Werte für x und y gesetzt. Damit sind die folgenden zwei Werte für y und möglich.
Das war einfach. Leider ist die Synchronisation der Abläufe relativ teuer. Die Freiheit des Systems die Abläufe zu optimieren ist deutlch eingeschränkt, da nur zwei mögliche Ausführungsreihenfolgen des Programms möglich sind.
Das ändert sich, wenn x und y zu atomaren Variablen werden.
Wie geht's weiter?
Im nächsten Artikel kommt die sequenzielle Konsistenz zum Einsatz.
Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library". Hole dir dein E-Book. Unterstütze meinen Blog.
Weiterlesen...