Es gibt einige beispielhafte Klassen von Containern in Pseudocode:
%Vor%Wie kann dieser Behälter fadensicher gemacht werden? Ich habe von Mutexen gehört - wo sollten diese Mutexe platziert werden? Sollte Mutex für eine Klasse statisch oder vielleicht global sein? Was ist eine gute Bibliothek für diese Aufgabe in C ++?
Zunächst sollten Mutexe für eine Klasse nicht statisch sein, solange Sie mehr als eine Instanz verwenden. Es gibt viele Fälle, in denen Sie sie verwenden sollten oder sollten. Also, ohne Ihren Code zu sehen, ist es schwer zu sagen. Denken Sie daran, sie werden verwendet, um den Zugriff auf gemeinsame Daten zu synchronisieren. Daher ist es ratsam, sie in Methoden zu platzieren, die den Status des Objekts ändern oder sich darauf verlassen. In Ihrem Fall würde ich einen Mutex verwenden, um das ganze Objekt zu schützen und alle drei Methoden zu sperren. Wie:
%Vor%Mutex als Instanzvariable der Klasse hinzufügen. Initialisieren Sie es im Konstruktor, und sperren Sie es am Anfang jeder Methode, einschließlich des Destruktors, und entsperren Sie es am Ende der Methode. Das Hinzufügen eines globalen Mutex für alle Instanzen der Klasse (statischer Member oder nur im globalen Gültigkeitsbereich) kann eine Leistungseinbuße darstellen.
Das ist auch eine sehr schöne Sammlung von Lock-Free-Containern (einschließlich Karten) von Max Khiszinsky
Hier ist die Dokumentationsseite:
Es kann etwas einschüchternd sein, um loszulegen, da es vollständig generisch ist und erfordert, dass Sie eine gewählte Speicherbereinigungsstrategie registrieren und diese initialisieren. Natürlich ist die Threading-Bibliothek konfigurierbar und Sie müssen das auch initialisieren:)
Siehe die folgenden Links für einige erste Informationen:
(cd build && ./build.sh ----debug-test
für Debug-Build) Hier ist die Basisvorlage für 'main':
%Vor%Vergessen Sie nicht, zusätzliche Threads anzuhängen, die Sie verwenden:
%Vor%1 ( darf nicht mit der kompakten Datenstrukturbibliothek von Google verwechselt werden)
Erstens: Austauschbare Zustände zwischen Threads sind schwer . Sie sollten eine Bibliothek verwenden, die geprüft und debuggt wurde.
Nun, da es gesagt wird, gibt es zwei verschiedene funktionale Probleme:
Die Idee mehrerer Operationen besteht darin, dass mehrere Zugriffe auf denselben Container nacheinander unter der Kontrolle einer einzelnen Entität ausgeführt werden müssen. Sie erfordern, dass der Aufrufer den Mutex für die Dauer der Transaktion "hält", so dass nur it den Status ändert.
1. Atomare Operationen
Dieser erscheint einfach:
Leider ist es auch einfach falsch.
Das Problem ist Re-Entrance. Es ist wahrscheinlich, dass einige Methoden andere Methoden für dasselbe Objekt aufrufen. Wenn diese wieder versuchen, den Mutex zu greifen, erhalten Sie eine totale Sperre.
Es ist möglich, einspringende Mutexe zu verwenden. Sie sind etwas langsamer, erlauben es aber demselben Thread, einen bestimmten Mutex so weit wie möglich zu sperren. Die Anzahl der Freischaltungen sollte der Anzahl der Sperren entsprechen, also noch einmal RAII.
Ein anderer Ansatz besteht darin, Dispatch-Methoden zu verwenden:
%Vor% Die public
-Methoden sind einfache Weiterleitungen zu private
work-methods und sperren einfach. Dann muss man nur sicherstellen, dass private Methoden niemals den Mutex nehmen ...
Natürlich gibt es Risiken, dass Sie versehentlich eine Sperrmethode von einer Arbeitsmethode aus aufrufen. In diesem Fall blockieren Sie. Lesen Sie weiter, um dies zu vermeiden;)
2. Mehrere Operationen
Das kann nur erreicht werden, wenn der Anrufer den Mutex hält.
Die allgemeine Methode ist einfach:
Ich persönlich bevorzuge einen viel gesunden Ansatz.
Zuerst erstelle ich ein "Datenbündel", das einfach die Klassendaten darstellt (+ ein Mutex), und dann stelle ich ein Proxy
bereit, das den Mutex ergreift. Die Daten sind gesperrt, so dass der Proxy nur auf den Status zugreifen kann.
Beachten Sie, dass es vollkommen sicher ist, dass der Proxy seine eigenen Methoden aufruft. Der Mutex wird automatisch vom Destruktor freigegeben.
Der Mutex kann immer noch reentrant sein, wenn mehrere Proxys gewünscht werden. Aber wirklich, wenn mehrere Proxies beteiligt sind, wird es in der Regel zu einem Durcheinander. Im Debug-Modus ist es auch möglich, eine "Überprüfung" hinzuzufügen, dass der Mutex nicht bereits von diesem Thread gehalten wird (und bestätigen, wenn dies der Fall ist).
3. Erinnerung
Die Verwendung von Sperren ist fehleranfällig. Deadlocks sind eine häufige Fehlerursache und treten auf, sobald Sie zwei Mutexe (oder einen und Re-Entrance) haben. Wenn möglich, bevorzugen Sie höherwertige Alternativen.
Tags und Links c++ multithreading