Потокобезопасный способ увеличить и вернуть целое число в Delphi - PullRequest
14 голосов
/ 25 октября 2010

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

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

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

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

Ответы [ 3 ]

37 голосов
/ 25 октября 2010

Вы можете использовать функции 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;
15 голосов
/ 25 октября 2010

Самый простой способ - просто позвонить InterlockedIncrement, чтобы выполнить работу.

5 голосов
/ 27 сентября 2015

С современными компиляторами Delphi лучше использовать Инкремент функция класса 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;

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

...