2010-10-25 28 views
14
返回一个整数

在单线程应用程序我用这样的代码:线程安全的方式来增加和德尔福

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

这当然可以被实现为一个单独的对象,等等 - 我我只是举了一个最简单的例子。

问:如何修改此函数(或设计一个类)以便从并发线程安全地实现相同的结果?

+0

感谢您的快速解答,每个人。我不知怎么地设法说服自己,互锁增量正在增加现有价值而不返回它 - 并不是说​​这样做会有任何意义,但我仍然坚持这一点。再次感谢。 – 2010-10-26 14:00:04

回答

35

您可以使用Interlocked*功能:

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

更现代的德尔福版本已经改名这些方法为Atomic*(像AtomicDecrementAtomicIncrement等),所以示例代码变成这样:

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

+1也用于举例。 – 2010-10-25 17:20:33

+5

和+1来显式声明{$ J +}。虽然我宁愿让GetNextUID成为一个类函数,但为了FUID而使用类var,仅仅是因为我不喜欢滥用常量。 – 2010-10-25 21:32:32

+0

注意:FireMonkey中没有互锁功能(应该有跨平台的方式来递增/递减?) – 2017-07-16 15:13:10

15

最简单的方法可能是拨打InterlockedIncrement来完成这项工作。

+0

但注意:FireMonkey不可用。跨平台的方式来增加/减少? – 2017-07-16 15:13:49

4

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

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

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

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