Ian*_*oyd 22 delphi multithreading critical-section readerwriterlock readerwriterlockslim
那里有更快的那种TMultiReadExclusiveWriteSynchronizer吗?FastCode也许吧?
从Windows Vista开始,Microsoft添加了Slim Reader/Writer锁.它的性能比Delphi 好得多TMultiReadExclusiveWriteSynchronizer.不幸的是,它只存在于Windows Vista及更高版本中,这是很少有客户真正拥有的东西.
据推测,Slim Reader/Writer lock在本机中使用的概念可以在本机Delphi代码中重做 - 但有人做过吗?
我有一种情况,即获取和释放锁定TMultiReadExclusiveWriteSynchronizer(即使没有争用 - 单个线程),导致100%的开销(操作时间加倍).我可以在没有锁定的情况下运行,但是我的类不再是线程安全的.
有更快的TMultiReadExclusiveWriteSynchronizer吗?
注意:如果我使用TCriticalSectioni,只会遭受2%的性能损失(尽管已知关键部分在获取成功时很快,即它是单线程并且没有争用).CS的缺点是我失去了" 多个读者 "的能力.
使用TMultiReadExclusiveWriteSynchronizer相当长的时间在内部BeginRead和EndRead:

然后移植代码以使用Window自己的SlimReaderWriter Lock(其中一些代码重写,因为它不支持递归锁定),并分析了resutls:
TMultiReadExclusiveWriteSynchronizer:每次迭代
10,698 ns 10,697,772,613 ns,迭代1,000,000次
SRWLock:每次迭代
8,802 ns,8,801,678,339 ns,迭代1,000,000次
Omni Reader-Writer lock:每次迭代8,941 ns,
8,940,552,487 ns,迭代1,000,000次
使用SRWLocks(又名Omni的旋转锁)时,性能提高了17%.
现在,我不能永久地切换代码以使用Windows Vista SRWLocks,因为有些客户仍然在Windows XP上.
Slim锁只是小心使用InterlockedCompareExchange功能; 但比我能成功使用更加小心.我这个远离刚刚偷涉及的140个机器指令,并完成它.
TOmniMREW从OmniThreadLibrary声称更快,更轻量级:
OTL是一个优秀的线程库,BTW.
TOmniReaderWriterLock = class(TInterfacedObject, IReaderWriterLock)
private
omrewReference: Integer;
public
{ IReaderWriterLock }
procedure BeginRead;
procedure EndRead;
procedure BeginWrite;
procedure EndWrite;
end;
{ TOmniReaderWriterLock }
procedure TOmniReaderWriterLock.BeginRead;
var
currentReference: Integer;
begin
//Wait on writer to reset write flag so Reference.Bit0 must be 0 than increase Reference
repeat
currentReference := Integer(omrewReference) and not 1;
until currentReference = Integer(InterlockedCompareExchange(Pointer(omrewReference), Pointer(Integer(currentReference) + 2), Pointer(currentReference)));
end;
procedure TOmniReaderWriterLock.EndRead;
begin
//Decrease omrewReference
InterlockedExchangeAdd(@omrewReference, -2);
end;
procedure TOmniReaderWriterLock.BeginWrite;
var
currentReference: integer;
begin
//Wait on writer to reset write flag so omrewReference.Bit0 must be 0 then set omrewReference.Bit0
repeat
currentReference := omrewReference and (not 1);
until currentReference = Integer(InterlockedCompareExchange(Pointer(omrewReference), Pointer(currentReference+1), Pointer(currentReference)));
//Now wait on all readers
repeat
until omrewReference = 1;
end;
procedure TOmniReaderWriterLock.EndWrite;
begin
omrewReference := 0;
end;
Run Code Online (Sandbox Code Playgroud)