【问题标题】:Thread-safe way to increment and return an integer in Delphi在 Delphi 中增加和返回整数的线程安全方法
【发布时间】:2011-04-30 08:04:55
【问题描述】:

在单线程应用程序中,我使用如下代码:

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

这当然可以实现为单例对象等 - 我只是给出最简单的示例。

问:如何修改这个函数(或设计一个类)以从并发线程中安全地获得相同的结果?

【问题讨论】:

  • 感谢大家的快速解答。我以某种方式设法说服自己 interlockedincrement 在不返回它的情况下增加了现有的值 - 并不是说​​那样有任何意义,但我仍然坚持这一点。再次感谢。

标签: multithreading delphi thread-safety increment


【解决方案1】:

您可以使用Interlocked* 函数:

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

更现代的 Delphi 版本已将这些方法重命名为 Atomic*(如 AtomicDecrementAtomicIncrement 等),因此示例代码变为:

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

【讨论】:

  • 和 +1 用于明确声明 {$J+}。虽然我更愿意让 GetNextUID 成为一个类函数并为 FUID 使用一个类 var,只是因为我不喜欢滥用常量。
  • 注意:FireMonkey 中没有联锁功能(应该有跨平台的方式来增加/减少?)
  • @AnotherProg 他们替换了前缀(见编辑),现在你可以更改 AtomicIncrement 和类似的。
【解决方案2】:

对于现代 Delphi 编译器,最好使用 System.SyncObjs 单元中 TInterlocked 类的 Increment 函数。像这样的:

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

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

这有助于保持代码独立于平台。

【讨论】:

    【解决方案3】:

    最简单的方法可能就是致电InterlockedIncrement 来完成这项工作。

    【讨论】:

    • 但请注意:在 FireMonkey 中不可用。跨平台递增/递减方式?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多