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;
Это помогает поддерживать независимость кода от платформы.