在多线程编程中,我们可以找到两个或多个线程/任务之间数据传输同步的不同术语。用于无阻塞多线程同步的无锁定,无等待和等待自由度算法
当正是我们可以说,一些算法是:
1)Lock-Free
2)Wait-Free
3)Wait-Freedom
我明白了什么是指无锁的,但是当我们可以说,一些同步算法是无等待还是等待,自由? 我已经取得了一些代码(环形缓冲区)为多线程同步,并使用无锁的方法,但是:
- 算法预测该程序的最长执行时间。
- 在开始时调用此例程的线程设置唯一引用(在此例程内部)。
- 正在调用相同例程的其他线程检查此引用,并且它是否设置为比计算第一个涉及线程的CPU滴答计数(度量时间)。如果那段时间很长时间会中断当前涉及的线程的工作并且会覆盖他的工作。
- 由于任务调度程序中断而未完成作业的线程(放置在最后)如果不属于他,请检查参考是否重复该作业。
所以这个算法不是真正的无锁,但没有使用内存锁,其他相关的线程可以等待(或不)一定的时间才能覆盖重置线程的工作。
新增RingBuffer.InsertLeft功能:
function TgjRingBuffer.InsertLeft(const link: pointer): integer;
var
AtStartReference: cardinal;
CPUTimeStamp : int64;
CurrentLeft : pointer;
CurrentReference: cardinal;
NewLeft : PReferencedPtr;
Reference : cardinal;
label
TryAgain;
begin
Reference := GetThreadId + 1; //Reference.bit0 := 1
with rbRingBuffer^ do begin
TryAgain:
//Set Left.Reference with respect to all other cores :)
CPUTimeStamp := GetCPUTimeStamp + LoopTicks;
AtStartReference := Left.Reference OR 1; //Reference.bit0 := 1
repeat
CurrentReference := Left.Reference;
until (CurrentReference AND 1 = 0)or (GetCPUTimeStamp - CPUTimeStamp > 0);
//No threads present in ring buffer or current thread timeout
if ((CurrentReference AND 1 <> 0) and (AtStartReference <> CurrentReference)) or
not CAS32(CurrentReference, Reference, Left.Reference) then
goto TryAgain;
//Calculate RingBuffer NewLeft address
CurrentLeft := Left.Link;
NewLeft := pointer(cardinal(CurrentLeft) - SizeOf(TReferencedPtr));
if cardinal(NewLeft) < cardinal(@Buffer) then
NewLeft := EndBuffer;
//Calcolate distance
result := integer(Right.Link) - Integer(NewLeft);
//Check buffer full
if result = 0 then //Clear Reference if task still own reference
if CAS32(Reference, 0, Left.Reference) then
Exit else
goto TryAgain;
//Set NewLeft.Reference
NewLeft^.Reference := Reference;
SFence;
//Try to set link and try to exchange NewLeft and clear Reference if task own reference
if (Reference <> Left.Reference) or
not CAS64(NewLeft^.Link, Reference, link, Reference, NewLeft^) or
not CAS64(CurrentLeft, Reference, NewLeft, 0, Left) then
goto TryAgain;
//Calcolate result
if result < 0 then
result := Length - integer(cardinal(not Result) div SizeOf(TReferencedPtr)) else
result := cardinal(result) div SizeOf(TReferencedPtr);
end; //with
end; { TgjRingBuffer.InsertLeft }
您可以找到RingBuffer单位在这里:RingBuffer,CAS功能:FockFreePrimitives和测试程序:RingBufferFlowTest
这看起来像一个家庭作业问题。如果是的话,你应该标记它的功课。人们会帮助你,但没有给你完整的答案,所以你可以为自己学习一些东西。如果这不是一个家庭作业问题,你应该描述你正在尝试做什么以及哪个部分有问题。 – 2009-09-21 08:56:49
谢谢西蒙。我已经记下了更多的细节。 – 2009-09-21 09:45:18
那么,有什么问题呢? – Seb 2009-10-24 13:05:20