Thread-safe способ увеличения и возврата целого числа в Delphi

В однопоточном приложении я использую такой код:

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

Это, конечно, может быть реализовано как одноэлементный объект и т.д. - я просто даю простейший возможный пример.

Q: Как я могу изменить эту функцию (или создать класс), чтобы безопасно достичь того же результата из параллельных потоков?

Ответы

Ответ 1

Вы можете использовать функции Interlocked*:

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

Более современные версии Delphi переименовали эти методы в Atomic* (например, AtomicDecrement, AtomicIncrement и т.д.), поэтому код примера станет следующим:

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

Ответ 2

Самый простой способ - просто вызвать InterlockedIncrement для выполнения задания.

Ответ 3

С современными компиляторами Delphi лучше использовать Increment функцию класса TInterlocked из блока System.SyncObjs. Что-то вроде этого:

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

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

Это помогает поддерживать независимость кода от платформы.