STL-Queue Zugriffsprobleme
-
In einen Queue werden schnell viele Werte geschrieben und wieder ausgelesen. Aber anscheinend zu schnell und zu oft. Denn es passiert zu oft, dass gleichzeitig (Threads!) versucht wird, zu lesen und zu schreiben. Und das mag der Queue wohl nicht. Besonders die push()-Funktion reagiert mit trotziger Langsamkeit.
Um das zu vermeiden, habe ich das so gelöst:
//Rein; in einem 1ms-Timer if(!QueueInUse) { QueueInUse = true; Queue.push(Wert); QueueInUse = false; } else { VerworfeneWerte++; } //Raus; in einer Schleife in einem anderem Thread if(!QueueInUse) { QueueInUse = true; Wert = Queue.front(); Queue.pop(); QueueInUse = false; } //sonst bleibt der Wert halt drin
Aber natürlich gefällt mir nicht wirklich, dass Werte, die es nicht in den Queue geschafft haben, verschwinden. Habe für solche Werte einen weiteren Queue ausprobiert, der dann in den Hauptqueue übertragen wird sobald der frei ist. Nur kommt schon der Timer schon wieder angerannt, bevor ich die Arbeit mit dem zweiten Queue beendet habe -> Noch ein Zugriffskonflikt.
Nun, da ich denke, dass ich so nicht weiter komme, frage ich mal euch: Gibt es einen Queue, der gleichzeitiges lesen und schreiben ermöglicht? Oder gibt es eine Möglichkeit, den Zugriff besser zu regeln?
Falls noch Fragen zum Verständnis offen sind, werde ich die natürlich gerne beantworten. (Ach, wie bin ich doch selbstlos. :D)
-
Aus Performance-Gründen sind die STL-Container nicht threadsafe. Dir bleibt
nichts anders übrig als nach einer LIB zu suchen die synchronisierte Container
anbietet oder dir die Zugriffe auf den Container selbst durch eines der
üblichen Verfahren zu synchronisieren.
-
Dummerweise finde ich keine Lib, die das machen könnte. Entweder sind meine Suchbegriffe dämlich oder ich bin der Einzige mit diesem einzigartigem Problem
Und was wäre "eines der üblichen Verfahren"? Warten, bis der Queue wieder frei zur Benutzung ist, kann ich nicht. (Wie gesagt: 1ms - Timer)
-
mach doch n MUTEX in die funktionen rein anstatt das mit der true/false variante
damit verlierst du nix und es wird safeafaik zumindest, so genau kenn ich mit threads noch net aus, aber soweit ich das weiß ist das ja so
MfG
-
Mutex? Kann man das essen?
Wikipedia schrieb:
Im einfachsten Fall besteht ein Semaphor aus einem Bit, das gesetzt sein kann oder nicht, was auch binärer Semaphor oder Mutex genannt wird. Ein Prozess, der einen kritischen Bereich betritt, löscht das Semaphor-Bit. Dies verhindert das Betreten des Bereichs durch andere Prozesse. Der Semaphor wird wieder gelöst, wenn der Prozess den kritischen Bereich verlässt. Wartende Prozesse werden dann nacheinander aktiviert.
Ist das nicht sowas wie das, was ich da verbrochen habe?
-
Generic++ ist nicht nur selbst multithread-safe, sondern beinhaltet auch alle wichtigen Klassen, um Threads zu starten, zu verwalten und zu synchronisieren: Threads, Threadvariablen, verschiedene Arten von Semaphoren sowie eine Monitorklasse.
-
Zum Glück habe ich eine Ausrede gefunden, bevor ich mich nochmal mit meiner Dummheit blamiert hätte: Mein Chef würde die Ausgabe für Generic++ kaum genehmigen.
-
Achso, das ist komerziell...
-
Redhead schrieb:
Aus Performance-Gründen sind die STL-Container nicht threadsafe.
Eine Aufrufkombination wie:
Wert = Queue.front(); Queue.pop();
kannst du nicht sinnvoll allein über den Container thread-safe machen. Der Container kann sinnvoll nur einzelne Operationen schützen. Angenommen die einzelnen Funktionen wären thread-safe (was sie bei vielen STL-Implementationen sind), dann hast du hier immer noch eine race-condition. Schließlich kann ein anderer Thread zwischen dem Aufruf von front() und pop() die Queue verändern.
Wenn es sich bei der Queue also um eine geteilte Ressource handelt, dann musst du sie extern schützen. Oder du musst die Queue wrappen und eine "apply"-Funktion anbieten, die z.B. ein Funktionsobjekt entgegennimmt und damit eine Reihe von Aufrufen schützen kann.Siehe z.B. Executing Around Sequences
-
Die STL container sind nicht threadsicher, klar.
Aber es gibt keinen Grund, die nicht threadsicher zu machen, wenn mans baucht ....
Prinzipiell musst alle Zugriffe Kapseln und Nen Lock(Mutex) davorschalten.
Die Mechanismen sind dann natuerlich nimmer plattformunabhaengig ... oder du verwendest ne lib die dir fuer mehrere Betriebssysteme die funktionlaitaeten mappt ....
Unter windows, schau mal nach "CriticalSection"
mit der pthread kenn ich mich ned so aus ...Ich verwend unter windows auch die STL extensiv in ner Multithreaded umgebung.
Ciao ...
-
Selbst wenn ein anderer Thread zwischen front() und pop() etwas in den Thread schieben würde, wäre das kein Problem. (logisch betrachtet - vorne ist ja wurscht, was hinten passiert.) Trotzdem hat der Queue damit Probleme.
Oder du musst die Queue wrappen und eine "apply"-Funktion anbieten, die z.B. ein Funktionsobjekt entgegennimmt und damit eine Reihe von Aufrufen schützen kann
Äh... was?
Wie man einen Lock/Mutex bastelt, kapiere ich ja eben nicht. Die Bücher, die sich hier stapeln auch nicht.
-
Wie man einen Lock/Mutex bastelt, kapiere ich ja eben nicht.
Ein beliebiges Einsteigerbuch zum Thema Multithreading sollte helfen.
Oder du musst die Queue wrappen und eine "apply"-Funktion anbieten, die z.B. ein Funktionsobjekt entgegennimmt und damit eine Reihe von Aufrufen schützen kann
Äh... was?
[/quote]
Es geht darum aus eine Seuqenz von Operationen eine atomare Operation zu machen. Wenn du allerdings nicht weißt, was ein Mutex/Lock/Monitor usw. ist, dann bringt es wenig hier weiter zu schreiben.
-
Ich frage mich wie man eine Multithreaded Anwendung schreiben kann ohne jemals was von nem Mutex/Lock gehört zu haben.
HEZ schrieb:
In einen Queue werden schnell viele Werte geschrieben und wieder ausgelesen. Aber anscheinend zu schnell und zu oft. Denn es passiert zu oft, dass gleichzeitig (Threads!) versucht wird, zu lesen und zu schreiben. Und das mag der Queue wohl nicht. Besonders die push()-Funktion reagiert mit trotziger Langsamkeit.
-
eViLiSSiMo schrieb:
Ich frage mich wie man eine Multithreaded Anwendung schreiben kann ohne jemals was von nem Mutex/Lock gehört zu haben.
Nun, man zieht einen Timer auf das Hauptformular... tja... fertig.
Aber gute Idee. Ich schmeiß das Projekt in den Papierkorb und sag meinem Chef, dass du gesagt hast, ich könne das nicht machen. Danke, hätte nicht gedacht, dass es so einfach geht.HumeSikkins schrieb:
Ein beliebiges Einsteigerbuch zum Thema Multithreading sollte helfen.
Ein beliebiges?! Da macht man sich die Mühe und kauft jedes verdammte Buch, in dem das Wort "Thread" vorkommt (wie ich es immer mache, wenn ich einen Timer auf das Formular ziehe) und dann sagst du, es hätte auch ein beliebiges getan??
Sich hier bitte irgendwas Versöhnliches zur Beruhigung vorstellen; mir fällt gerade nichts ein<
-
Kannst du den queue nicht einfach in einen Singelton stecken, der
sich dann merkt ob der queue gerade in Benutzung ist... ?Devil
-
Welche Timer verwendest du denn? Den mit SetTimer? Dann sollte es gar nicht zu Konflikten kommen.
-
vergiss die frage. war dumm von mir.
-
devil81 schrieb:
Kannst du den queue nicht einfach in einen Singelton stecken, der sich dann merkt ob der queue gerade in Benutzung ist... ?
Was würde denn dann passieren, wenn er in Benutzung ist? Das müsste man doch dann auch abfragen, oder?
-
-
-
Wer kommt als nächstes? bluehead?
Ich denke immer noch nicht, dass die Lösung eines einzelnen Teilproblems (der Kategorie "sieht ja niemand")den Aufwand größerer finanzieller und zeitlicher Ressourcen rechtfertigt... sicher ist die Synchronisierung von Threads ein sehr interessantes und wissenswertes Thema. Ich würde jedoch damit gerne warten, bis ich mal Zeit für Weiterbildungen habe.