(18.02.2022 09:29 )GerdW schrieb: Hallo creo,
Zitat:Und warum müssen dann beide Schleifen die exakt gleiche Datenstruktur verwenden?
Die erste Schleife filtert nur die CAN-Messages anhand ihrer ArbID. "Gute" Messages werden dann an die zweite Schleife weitergeschickt: sinnvollerweise aber per Queue und nicht per Notifier! (Du willst doch alle "guten" Messages verarbeiten, oder?)
Die zweite Schleife nimmt die Messages entgegen und wertet die enthaltenen Signale aus. Die Signalwerte werden dann in einer anderen Datenstruktur gespeichert…
[quote]Wenn ich dich richtig verstanden habe, wäre das aber auch bei einer globalen Variable oder FGV problematisch, richtig?
Ja, die Problematik mit RaceConditions tritt auch hier auf.
Bei der FGV hast du zumindest den Vorteil, dass du nur einen zentralen Datenbuffer hast und den Zugriff auf einzelne Elemente darin kapseln kannst.
Um das zu ergänzen: Durch die Benutzung der FGV kannst du garantieren, dass jeder Befehl den du an die FGV schickst atomar ausgeführt wird (daher ganz oder garnicht). Das sorgt zumindest für Datenkonsistenz in deinem Cluster, da verhindert wird, dass an einem Wert zuerst der eine Prozess zuerst zum Zuge kommt und dann der andere, bei der anderen umgekehrt.
Beispiel wie sowas zu Problemen führen kann:
A und B wollen dir Geld überweisen. Jede Überweisung besteht aus Lesen deines IST Kontostands und anschließendem erhöhen um den Überweisungsbetrag. Wenn alles gut geht sieht das so aus:
A lesen, A rechnen, A schreiben, B lesen, B rechnen, B schreiben.
Ist die Leseschreiboperation aber nicht atomar, dann kann als eine Variante das passieren:
A lesen, A rechnen, B lesen, A schreiben, B rechnen, B schreiben
Du verlierst dadurch die Gutschrift von A, das Geld wird bei A aber trotzdem abgezogen (hier kommt es ja nicht zum "Konflikt" bei der Ausführung). Das führt zu einem inkonsistenten Zustand (das Geld das vorher da war ist weder bei A noch bei dir).
Klassische Racingcondition. Machst du jedoch die Schreib-Lese-Operation über eine FGV atomar (ergo die wird in einer Ausführung der FGV abgearbeitet), dann vermeidest du diese Racingcondition zumindest dahingehend, dass dir egal ist welche Überweisung zuerst abgearbeitet wird. Du gewinnst dadurch möglichst schnelle Nebenläufigkeit, bei Verhinderung schädlicher Racing Conditions.
Das Spielchen kannst du im Prinzip so weit treiben, dass du über die FGV Schreib-/Lesesperren verwaltest und dadurch (Auswirkungen von) Racing Conditions weitgehend ausschalten kannst. Im Prinzip also auch für parallele Abarbeitung ein mächtiges Werkzeug.
Die zweite Variante Racing condition ist, dass deine Verarbeitungsschleife nicht schnell genug ist um alle ankommenden schnell genug zu verarbeiten. Das kannst du über eine Queue besser puffern (da du eine größe Vorgeben kannst). Damit fängst du das Problem aber nur ab wenn die Mittlere Ausführungszeit hoch genug ist um alles abzuarbeiten. Ist die Ausführungszeit zu niedrig läuft dir auch die Queue irgendwann voll, oder bei nicht eingeschränkter Größe der Queue crasht dein Programm irgendwann weil dir der RAM ausgeht. Vorher wirds dann noch langsam weil du anfängst ständig in die Auslagerungsdatei zu schreiben.