我们中的许多人可能找到或想出了以下同步原语:
获取锁定(代码在Pascal中):
while Cardinal(InterlockedExchange(fAccess, 1)) <> 0 do
Sleep(0);
并发布它:
InterlockedExchange(fAccess, 0);
当我发现它与嵌套调用不兼容时,我决定让它变得更好并实现新的Aqcuire变体,如下面的代码(让我们调用Acquire / Release上面的片段)
Acquired:=false;
repeat
Acquire;
if (fData.Thread = 0) or (fData.Thread = GetCurrentThreadId) then
begin
fData.Thread:=GetCurrentThreadId;
Inc(fData.Level);
Acquired:=true;
end
else
Inc(fData.Failures);
SleepAfter:=(not Acquired);
Release;
if SleepAfter then
Sleep(0);
until Acquired;
和新版本
Acquire;
Dec(fData.Level);
if fData.Level=0 then
fData.Thread := 0
Release;
这很有效,但令我困惑的是失败次数很少(至少在单核系统上)。对于三个测试线程,每个值增加10,000,000次,这个代码无法获得锁定的次数大约为72.我很高兴,但另一方面我无法理解背后的机制。因此,任何唤醒线程都会发现所有其他线程大多数时间都处于休眠状态。为什么?如果线程存在于不同的核心上,那么冲突的数量会显着增加吗?