2010-10-25 7 views
14

In einer Single-Threaded-Anwendung zu erhöhen und kehre ich folgenden Code verwenden:Gewinde sichere Art und Weise eine ganze Zahl in Delphi

Interface 
    function GetNextUID : integer; 
Implementation 
    function GetNextUID : integer; 
    const 
     cUID : integer = 0; 
    begin 
     inc(cUID); 
     result := cUID; 
    end; 

Dies natürlich als Singleton-Objekt implementiert werden könnte, usw. - I Ich gebe nur das einfachste mögliche Beispiel.

F: Wie kann ich diese Funktion ändern (oder eine Klasse entwerfen), um das gleiche Ergebnis sicher von gleichzeitigen Threads zu erreichen?

+0

Danke für die schnellen Antworten, alle. Ich hatte es irgendwie geschafft, mich selbst davon zu überzeugen, dass das verzahnte Inkrementieren den Wert an Ort und Stelle erhöhte, ohne es zurückzugeben - nicht, dass es so einen Sinn ergeben würde, aber ich blieb trotzdem dabei stecken. Danke noch einmal. –

Antwort

35

können Sie die Interlocked* Funktionen nutzen:

function GetNextUID : integer; 
    {$J+} // Writeble constants 
    const 
     cUID : integer = 0; 
    begin 
     Result := InterlockedIncrement(cUID); 
    end; 

Modernere Delphi-Versionen diese Methoden in Atomic* umbenannt (wie AtomicDecrement, AtomicIncrement, etc.), so dass der Beispielcode wird dieses:

function GetNextUID : integer; 
    {$J+} // Writeble constants 
    const 
     cUID : integer = 0; 
    begin 
     Result := AtomicIncrement(cUID); 
    end; 
+0

+1 für auch das Beispiel geben. –

+5

und +1 für die explizite Angabe von {$ J +}. Obwohl ich es vorziehen würde, GetNextUID zu einer Klassenfunktion zu machen und eine Klassenvariable für FUID zu verwenden, nur weil ich es nicht mag, Konstanten zu missbrauchen. –

+0

Hinweis: Interlocked-Funktionen sind in FireMonkey nicht verfügbar (es sollte eine plattformübergreifende Möglichkeit zum Inkrementieren/Dekrementieren geben?) –

15

Der einfachste Weg wäre wahrscheinlich, nur InterlockedIncrement zu rufen, um die Aufgabe zu erledigen.

+0

aber Hinweis: Nicht in FireMonkey verfügbar. Cross Platform Weg zu erhöhen/verringern? –

4

Mit modernen Delphi-Compilern ist es besser, Increment Funktion der Klasse TInterlocked von Einheit System.SyncObjs zu verwenden. Etwas wie dieses:

type 
    TMyClass = class 
    class var 
     FIdCounter: int64; 
    var 
     FId: int64; 
    constructor Create; 
    end; 

constructor TMyClass.Create; 
begin 
    FId := TInterlocked.Increment(FIdCounter); 
end; 

Dies hilft, den Code plattformunabhängig zu halten.