Das sollte dann meiner Meinung nach sicher sein, aber sicher bin ich mir nicht
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Betrifft also ein geteilter Speichernur den Zugriff? Eigentlich greifen selbst 100 Threads nie gleichzeitig auf ein Speicher zu, da jeder Schritt für Schritt abgearbeitet wird, oder nicht?
Richtig.
Aber wenn der Lese-Thread gerade das zu lesende Bild rendert (was ja Schritt für Schritt passiert), und du gerade bei Schreibe-Thread ein neues Bild an der Stelle einfügst, ließt der Lese-Thread in einem nicht mehr gültigem Speicher -> IMA
Was ohne Mutex geht ist zB in eine Long zu lesen und "gleichzeitig" zu schreiben, weil das jeweils nur ein "Schritt" ist.
Integerspeicherzugriffe sind die einzigen, die mit einer Operation auskommen, alle anderen benötigen mehrere Operationen,
was bei Zugriff mehrerer Threads unweigerlich zu undefiniertem Zustand führt.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Das Bild ändert sich nicht. Lediglich Werte wie Winkel und Position müssen paralell und permanent sein.
Ich muss mich korrigieren, es läuft so zwar Problemlos, führt dennoch zu einem sichtbaren ruckeln. Der Thread ist wie gesagt mit TryLockMutex abgesichert(am Zeichnen-Abschnitt) , wenn aber die äußeren Befehle dem Thread das Mutex an der Abfrage meistens klauen führt das wieder zum ruckeln.
ts-soft hat geschrieben:Integerspeicherzugriffe sind die einzigen, die mit einer Operation auskommen, alle anderen benötigen mehrere Operationen,
was bei Zugriff mehrerer Threads unweigerlich zu undefiniertem Zustand führt.
Das stimmt nicht. Die PB-Integer sind keine atomic Integer. Wenn man schreibt "a.i + 1", werden daraus trotzdem 3 ASM-Befehle generiert, nämlich Laden aus dem Speicher in ein Register, Wert erhöhen, und Zurückschreiben in den Speicher.
Naja, ich meinte auch nur die Lesezugriffe, hätte mich da wohl genauer ausdrücken müssen.
Danke für den Hinweis
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
ts-soft hat geschrieben:Naja, ich meinte auch nur die Lesezugriffe, hätte mich da wohl genauer ausdrücken müssen.
Selbst da kann es passieren, dass zwei Threads aus ein und der selben Variablen unterschiedliche Werte lesen, da jeder Thread auf einem anderen Core laufen kann und jeder Core seinen eigenen Cache hat. Ist bei beiden Cores diese Variable im Cache und ändert sie einer von beiden Threads, wird sie normalerweise nicht direkt in den Arbeitsspeicher geschoben oder in einen höheren gemeinsamen Cache, sodass der andere Thread den aktuellen Wert bekommen würde. Deswegen kann man normalerweise Variablen als atomic deklarieren. Diese werden nämlich immer frisch aus dem Arbeitsspeicher geholt und nach Änderung zurück in ihn geschrieben.
Mit zwei Listen arbeiten. Eine Liste zum hinzufügen und die andere Liste zum rändern.
Der Thread zum Rändern sperrt kurz die Liste zum hinzufügen und übernimmt diese zur Liste zum Rändern.
ts-soft hat geschrieben:Naja, ich meinte auch nur die Lesezugriffe, hätte mich da wohl genauer ausdrücken müssen.
Selbst da kann es passieren, dass zwei Threads aus ein und der selben Variablen unterschiedliche Werte lesen, da jeder Thread auf einem anderen Core laufen kann und jeder Core seinen eigenen Cache hat. Ist bei beiden Cores diese Variable im Cache und ändert sie einer von beiden Threads, wird sie normalerweise nicht direkt in den Arbeitsspeicher geschoben oder in einen höheren gemeinsamen Cache, sodass der andere Thread den aktuellen Wert bekommen würde. Deswegen kann man normalerweise Variablen als atomic deklarieren. Diese werden nämlich immer frisch aus dem Arbeitsspeicher geholt und nach Änderung zurück in ihn geschrieben.
Atomic? Volatile wäre das doch, was du eben mit dem "höheren, gemeinsamen Cache" und "frisch aus dem Arbeitsspeicher" meinst. Aber dann braucht man immer noch atomarität der Zugriffe (das entspricht quasi locks drumrum), da ja auch echt parallel damit operiert werden kann, wodurch die Aussage über atomic wieder richtig wird. Atomic sichert jedoch nur Einzelzugriffe ab!
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.