如何仅使用compare_and_swap实现优先级锁定?

时间:2010-01-28 01:50:30

标签: locking compare-and-swap

只给出比较和交换,我知道如何实现锁定。

但是,我如何实现自旋锁

1)多个线程在尝试锁定时可以阻塞它 2)然后线程按照它们阻塞的顺序被解除锁定(并获取锁定)?

甚至可能吗?如果没有,我需要什么其他原语?

如果是这样,我该怎么做?

谢谢!

1 个答案:

答案 0 :(得分:0)

您将需要等待线程的列表。您需要以线程安全的方式添加和删除列表中的项目。您将需要能够睡眠无法获得锁定的线程。当锁定可用时,您需要能够唤醒1个线程。在linux中,您可以通过让线程等待信号来完成睡眠和等待。

现在有一种懒惰的方法,你可能不需要关心唤醒线程。这是我们的跳过列表的伪代码。这就是我们添加项目的方法。

cFails = 0
while (1) {
  NewState = OldState = State;
  if (cFails > 3 || OldState.Lock) {
    sleep();  // not too sophisticated, because they cant be awoken
    cFails = 0;
    continue;
  }

  Look for item in skiplist
  return item if we found it

  // to add the item to the list we need to lock it

  // ABA lock uses a version number
  NewState.Lock=1;
  NewState.nVer++;
  if (!CAS(&State,OldState, NewState)) {
    ++cFails;
    continue; 
  }

  // if the thread gets preempted right here, the lock is left on, and other threads
  // spinning would waste their entire time slice.

  // unlock
  OldState = NewState;
  NewState.Lock = 0;
  NewState.nVer++;
  CAS(&State, OldState,NewState);  
}

我们希望跳过列表通常可以找到该项目,并且很少需要添加它。我们很少有竞争添加,即使有很多线程。我们在最糟糕的情况下对此进行了测试,其中包括大量线程添加和搜索数百万个项目到单个列表。结果是我们很少看到线程无法获得锁定。因此,针对预期案例的高性能的简单方法适用于我们。有一件坏事可能发生 - 一个线程被抢先拿着锁。那是什么时候cFails> 3抓住这个并等待线程等待,这样我们就不会浪费他们的时间片来进行一百万次无用的旋转。所以cFails设置得足够高,以至于它检测到锁的所有者没有活动。