2010-10-25 7 views
14

En una aplicación de subproceso único utilizo código como este:Hilo de seguridad manera de incrementar y devolver un número entero en Delphi

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

Esto podría, por supuesto, ser implementado como un objeto singleton, etc. - I' Estoy simplemente dando el ejemplo más simple posible.

P: ¿Cómo puedo modificar esta función (o diseñar una clase) para obtener el mismo resultado de manera segura a partir de subprocesos concurrentes?

+0

Gracias por las respuestas rápidas, a todos. De alguna manera me las había arreglado para convencerme de que el incremento entrelazado estaba incrementando el valor en su lugar sin devolverlo, no que tuviera ningún sentido de esa manera, pero de todos modos me quedé atrapado. Gracias de nuevo. –

Respuesta

35

Puede utilizar los Interlocked* funciones:

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

más modernas versiones de Delphi han cambiado el nombre de estos métodos en Atomic* (como AtomicDecrement, AtomicIncrement, etc), por lo que el código de ejemplo se convierte en esto:

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

+1 para también dar el ejemplo. –

+5

y +1 para indicar explícitamente {$ J +}. Aunque preferiría hacer de GetNextUID una función de clase y usar una clase var para FUID, solo porque no me gusta abusar de las constantes. –

+0

nota: funciones enclavadas no disponibles en FireMonkey (debe haber una forma de plataforma cruzada para incrementar/disminuir?) –

15

La manera más fácil sería simplemente llamar al InterlockedIncrement para hacer el trabajo.

+0

pero nota: no disponible en FireMonkey. ¿Forma de plataforma cruzada para incrementar/disminuir? –

4

Con los compiladores Delphi modernos, es mejor usar la función Increment de la clase TInterlocked de la unidad System.SyncObjs. Algo como esto:

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

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

Esto ayuda a mantener el código independiente de la plataforma.

Cuestiones relacionadas