为什么这个同步原语有效?

时间:2012-04-17 12:37:40

标签: multithreading winapi language-agnostic

我们中的许多人可能找到或想出了以下同步原语:

获取锁定(代码在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.我很高兴,但另一方面我无法理解背后的机制。因此,任何唤醒线程都会发现所有其他线程大多数时间都处于休眠状态。为什么?如果线程存在于不同的核心上,那么冲突的数量会显着增加吗?

0 个答案:

没有答案