2015-12-20 34 views
5

So nahm ich ein OS-Klasse im letzten Semester und wir hatten ein Nebenläufigkeit/Threading-Projekt. Es war ein Flughafen-Sim, der Flugzeuge landete/in die Richtung fliegen ließ, in die der Wind wehte. Wir mussten es in Java machen. Jetzt, wo das Finale vorbei ist und mir langweilig ist, versuche ich es in C++ 11 zu tun. In Java habe ich eine synchronisierte Variable für den Wind (0 - 360) in main verwendet und an die 3 Threads übergeben, die ich benutzt habe. Meine Frage ist: Können Sie das in C++ 11 tun? Es ist ein einfacher Leser/Schreiber, ein Thread schreibt/aktualisiert den Wind, die anderen 2 (Start/Land) lesen.Gemeinsame Variablen in C++ 11

Ich habe es funktioniert mit einer globalen Wind-Variable in meiner "threads.cpp" Implementierungsdatei. Aber gibt es eine Möglichkeit, eine Variable an so viele Threads zu übergeben, wie ich will und alle mithalten? Oder ist es eigentlich besser für mich, nur die globale Variable zu verwenden und nichts weiterzugeben? (Warum/warum nicht?) Ich habe mir std::ref() angesehen, aber das hat nicht funktioniert.

EDIT: Ich benutze bereits Mutex und lock_guard. Ich versuche nur herauszufinden, wie man eine Variable in allen Threads übergibt und auf dem neuesten Stand hält. Im Moment wird nur im Schreib-Thread aktualisiert.

Antwort

5

Sie können einen std::mutex mit std::lock_guard verwenden, um den Zugriff auf die freigegebenen Daten zu synchronisieren. Oder wenn die geteilten Daten in eine Ganzzahl passen, können Sie std::atomic<int> ohne Sperren verwenden.

Wenn Sie globale Variablen vermeiden möchten, übergeben Sie einfach die Adresse des gemeinsamen Status an die Thread-Funktionen, wenn Sie sie starten. Zum Beispiel:

void thread_entry1(std::atomic<int>* val) {} 
void thread_entry2(std::atomic<int>* val) {} 

std::atomic<int> shared_value; 
std::thread t1(thread_entry1, &shared_value); 
std::thread t2(thread_entry2, &shared_value); 
+0

Ja, genau das habe ich versucht! Es scheint fast so, als wäre es mehr ein Schmerz, als nur die globale Variable zu verwenden. Gibt es +/-, um das so zu machen? – lciamp

+3

Nun, die meisten Menschen halten globale Variablen für die meiste Zeit für eine schlechte Praxis. Macht das Testen zumindest schwieriger. –

1

Man könnte sagen, erstellen möchten, den Wind Objekt, auf dem Heap mit new durch einen std::shared_ptr. Übergeben Sie diesen Zeiger an alle interessierten Threads und verwenden Sie eine std::mutex und std::lock_guard, um es zu ändern.

+0

Danke. Ich muss shared_ptr auschecken.Ich mache gerade den Wechsel von C++ 98 zu 11, sollte eine lustige Winterpause sein! – lciamp

+1

Sie machen auch den Wechsel von Java zu C++ und das ist ein Drehpunkt, den Sie brauchen, um sich zu rühren. In Java werden automatisch Objekte auf dem Heap und Speicher erstellt, die für Sie verwaltet werden. In C++ müssen Sie diese Verantwortung selbst übernehmen. Aber es gibt einige großartige C++ 11 (und C++ 14!) Standard-Bibliothekshelfer, mit denen Sie sich auseinandersetzen müssen, um diese Reise so süß wie möglich zu gestalten. Willkommen in C++ Land, haben Sie eine tolle Winterpause! :)) –

2

Mit std::mutex und std::lock_guard mimicks, was eine Java-synchronisierte Variable tut (nur in Java geschieht dies heimlich ohne Sie zu wissen, in C++ machen Sie es explizit).

Jedoch ein Produzent (es gibt nur eine Richtung des Windes) und sonst nur Verbraucher, es genügt zu schreiben, um eine z. std::atomic<int> Variable mit entspannter Reihenfolge, und von dieser Variable von jedem Verbraucher zu lesen, wieder mit entspannter Reihenfolge. Wenn Sie nicht die Anforderung haben, dass die globale Ansicht aller Flugzeuge konsistent ist (aber dann müssten Sie eine Lockstep-Simulation ausführen, was das Threading sinnwidrig macht), besteht keine Notwendigkeit für eine Synchronisation, Sie müssen nur sicherstellen, dass jeder beliebige Wert vorhanden ist Flugzeug liest zu jeder Zeit ist schließlich richtig und dass keine verstümmelten Zwischenergebnisse auftreten können. Mit anderen Worten, Sie benötigen ein atomares Update.
Entspannte Speicherordnung ist auch ausreichend, denn wenn alles, was Sie lesen, ein Wert ist, brauchen Sie keine Vor-Vor-Garantien.

Ein atomares Update (oder besser: atomares Schreiben) ist mindestens eine Größenordnung, wenn nicht mehr, schneller. Atomare Lese- und Schreibvorgänge mit entspannter Reihenfolge sind in der Tat normale normale Lese- und Schreibvorgänge auf vielen (meisten) Mainstream-Architekturen.

Die Variable muss nicht global sein, Sie können sie auch im Gültigkeitsbereich der Simulationsschleife des Hauptthreads speichern und eine Referenz (oder einen Zeiger) an die Threads übergeben.

+0

huh. Klingt wie Atomic ist für mein Problem besser geeignet als Mutex/Lock_guard. Was ich tat, weil ich den Java-Code sah, den ich bereits geschrieben hatte, ging durch den Wert anstatt durch den Verweis. Ich sollte es versuchen. verwende atomare für den wind und mutex/lock_guard für die startbahnen. Danke für die Hilfe! – lciamp

+0

Mutex für die Piste ist sicherlich sinnvoll, da sich immer nur ein Flugzeug auf einer Piste befinden kann (ohne dass es unangenehm wird). Nur zum Abtasten der aktuellen Windrichtung braucht man nicht wirklich Mutex. – Damon

+0

Mit einem std :: atomic funktioniert sicherlich, aber das ist vorzeitige Optimierung. Da es mehrere Variablen gibt (Landebahn, Wind, ...), ist ein Mutex zum Schutz des gesamten Zustands das erste, was man sich vor Augen halten sollte. – galinette