Liste von Delphi-Datentypen mit 'thread-sicheren' Lese- / Schreiboperationen?

8

Sind boolesche Variablen Thread-sicher zum Lesen und Schreiben von einem Thread? Ich habe einige Newsgroup-Referenzen gesehen, um zu sagen, dass sie das sind. Sind andere Datentypen verfügbar? (Aufzählungstypen, vielleicht kleine Ints?)

Es wäre nett, eine Liste aller Datentypen zu haben, die sicher aus jedem Thread gelesen werden können und eine andere Liste, in die auch sicher in jeden Thread geschrieben werden kann, ohne auf verschiedene Synchronisationsmethoden zurückgreifen zu müssen.

    
Darian Miller 04.02.2009, 04:09
quelle

5 Antworten

7

Bitte beachten Sie, dass Sie im Wesentlichen alles in Delphi undhreadsafe machen können. Während andere auf boolesche Ausrichtungsprobleme hinweisen, verbirgt sich das eigentliche Problem.

Ja, Sie können einen booleschen Wert in einem beliebigen Thread lesen und in einen beliebigen booleschen Wert schreiben, wenn er korrekt ausgerichtet ist. Aber das Lesen von einem Booleschen, das du änderst, ist sowieso nicht unbedingt "threadsicher". Angenommen, Sie haben einen booleschen Wert, den Sie auf "true" setzen, wenn Sie eine Zahl aktualisiert haben, sodass ein anderer Thread die Zahl liest.

%Vor%

Aufgrund von Optimierungen macht der Prozessor TheNumber gelesen, bevor NumberUpdated gelesen wird, daher können Sie den alten Wert von TheNumber erhalten, obwohl Sie NumberUpdated zuletzt aktualisiert haben.

Aka, Ihr Code könnte zu:

werden %Vor%

Imho, eine Grundregel des Fausts:
"Lesevorgänge sind threadsicher. Schreibvorgänge sind nicht threadsicher."
Wenn Sie also einen Schreibschutz für die Daten mit der Synchronisation überall durchführen, lesen Sie den Wert, während ein Schreibvorgang möglicherweise auftreten kann.
Auf der anderen Seite, wenn Sie nur einen Wert in einem Thread lesen und schreiben, dann ist es threadsicher. So können Sie einen großen Teil des Schreibens an einem temporären Speicherort ausführen und dann eine Aktualisierung der anwendungsweiten Daten synchronisieren.

Bonus Klappentext:

Die VCL ist nicht Thread-sicher. Behalte alle Modifikationen von ui stuff im Hauptthread. Behalte auch die Erstellung aller UI-Sachen im Hauptthread.

Viele Funktionen sind auch nicht threadsicher, während andere oft von den Winapi-Aufrufen abhängig sind.

Ich denke nicht, dass eine "Liste" hilfreich wäre, da "threadsicher" eine Menge Sachen bedeuten kann.

    
PetriW 04.02.2009, 11:49
quelle
7

Dies ist keine Frage von Dateitypen, die Thread-sicher sind, aber es ist eine Frage dessen, was Sie mit ihnen tun. Ohne Sperren ist keine Operation threadsicher, das heißt einen Wert zu laden, dann zu ändern und dann zurückzuschreiben: eine Zahl inkrementieren oder dekrementieren, ein Element löschen oder setzen - sie sind alle nicht threadsicher.

Es gibt eine Reihe von Funktionen, die atomare Operationen ermöglichen: verriegelte Inkrementierung, verriegelte Dekrementierung und verriegelter Austausch. Dies ist ein allgemeines Konzept, nichts speziell für Windows, x86 oder Delphi. Für Delphi können Sie die InterlockedFoo () - Funktionen der Windows-API verwenden, um diese herum gibt es auch mehrere Wrapper. Oder schreibe deine eigenen. Die Funktionen arbeiten mit ganzen Zahlen, so dass Sie atomare Inkremente, Dekremente und den Austausch von ganzen Zahlen (32 Bit) mit ihnen haben können.

Sie können auch Assembler- und Präfix-Ops mit dem Sperrpräfix verwenden.

Weitere Informationen finden Sie auch in dieser StackOverflow-Frage .

    
mghie 04.02.2009 06:51
quelle
5

In der 32-Bit-Architektur sollten nur ordnungsgemäß ausgerichtete Dateitypen mit 32 Bit oder weniger als atomar betrachtet werden. 32-Bit-Werte müssen 4-ausgerichtet sein (die Adresse der Daten muss durch 4 teilbar sein). Vermutlich würden Sie nicht auf solch engem Niveau mit Interleaving arbeiten, aber theoretisch könnten Sie Double, Int64 oder Extended nicht-atomaren Write haben.

    
Eugene Yokota 04.02.2009 06:33
quelle
2

Da Multi-Core-RISC-Verarbeitung und separater Core-Cache-Speicher in der Mischung eines modernen Prozessors sind, ist es nicht mehr der Fall, dass irgendein "triviales" Hochsprachen-Lese- oder Schreib-Konstrukt (oder auch viele einmal) - Auf einmal 8086 "atomare" Montageanweisungen können als atomar angesehen werden. In der Tat, es sei denn, ein Assemblerbefehl ist speziell atomar konstruiert, ist er wahrscheinlich nicht atomar - und das schließt die meisten Mechanismen für Speicherlesevorgänge ein. Selbst eine lange Ganzzahl, die auf Assembler-Ebene gelesen wird, kann durch simultanes Schreiben von einem anderen Prozessorkern, der denselben Speicher teilt und asynchrone Cache-Aktualisierungsaktionen auf der RISC-Prozessor-Ebene verwendet, beschädigt werden. Denken Sie daran, dass auf einem Prozessor mit mehreren RISC-Kernen selbst Assemblersprachanweisungen nur "höhere" Codeanweisungen sind! Sie wissen nie wirklich, wie sie auf der Bit-Ebene implementiert werden, und es ist vielleicht nicht ganz das, was Sie erwartet haben, wenn Sie ein altes 8086 (Single-Core) Assembler-Handbuch gelesen haben. Windows stellt native Systemkompatible atomare Operatoren zur Verfügung, und Sie wären gut beraten, diese zu verwenden, anstatt irgendwelche Grundannahmen über atomare Operationen zu machen.

Warum die Windows-Operatoren verwenden? Eines der ersten Dinge, die Windows tut, ist festzustellen, auf welcher Maschine es läuft. Einer der Schlüsselaspekte, die es sicherstellen, ist, was atomare Operationen dort sind und wie sie funktionieren. Wenn Sie möchten, dass Ihr Code bei zukünftigen Prozessoren gut in die Zukunft passt, können Sie diesen Aufwand in Ihrem eigenen Code duplizieren (und ständig aktualisieren), oder Sie können die Tatsache nutzen, dass Windows bereits beim Start alles erledigt hat. Es integrierte dann den notwendigen Code zur Laufzeit in seine API.

Lesen Sie die MSDN-Seiten zu atomaren Operationen. Die Windows API zeigt diese für Sie an. Sie können manchmal klobig oder ungeschickt erscheinen - aber sie sind zukunftssicher und sie werden immer genau so funktionieren, wie es auf der Dose steht.

Woher weiß ich das? Nun, denn wenn sie es nicht tun würden - dann könnten Sie Windows nicht ausführen. Punkt. Es macht nichts, einen eigenen Code zu erstellen.

Immer wenn du Code schreibst, ist es immer eine gute Idee, Parsimony zu verstehen und Occam Rasiermesser . Mit anderen Worten, wenn Windows dies bereits tut und Ihr Code Windows zum Ausführen benötigt, dann verwenden Sie, was Windows bereits tut, anstatt viele alternative und zunehmend komplexe hypothetische Lösungen auszuprobieren, die funktionieren können oder nicht. Etwas anderes zu tun ist nur eine Verschwendung Ihrer Zeit (es sei denn natürlich, dass Sie sich darin befinden).

    
Alex T 11.03.2016 14:18
quelle
0

Der Indy-Code enthält einige atomare / threadsichere Datentypen in IdThreadSafe.pas:

  • TIdThreadSafeInteger
  • TIdThreadSafeBoolean
  • TIdThreadSafeString
  • TIdThreadSafeStringList und noch etwas ...
mjn 21.03.2009 18:49
quelle

Tags und Links