如何在无锁的并发队列中实现“ Front”方法?

时间:2019-11-25 23:54:18

标签: multithreading

我正在尝试实现并发无锁队列。我正在密切关注本文:https://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf 但是本文没有提供暴露Front()或Back()方法的安全方法。有Enqueue()和Dequeue()方法。 (本文阐述了无锁版本以及带锁的版本,我对前者感兴趣)。现在让我直接解决这个问题。在进行所有安全检查(类似于入队)之后,Front()函数的紧缩归结为:

1. if(local_copy_of_head == curr_shared_head) {  // Let's say I read this atomically. The equality means the head didn't move since the time I copied.
2.   return local_copy_of_head;
3. }

我想澄清一点,尽管这是有关如何实现Front()函数的问题,但是我主要对如何将上述代码段重构为没有任何锁的原子块感兴趣。 我担心的是,如果Thread1在执行第1行后被中断(我从原子上说了这一点),那么第二个线程清空了队列,Thread1被重新安排并返回了陈旧的结果。

1 个答案:

答案 0 :(得分:0)

不能。您可以制作一个糟糕的版本,该版本可以工作很多次,但总的来说是失败的。要消除无锁的奥秘,请用上一个术语“繁忙等待”代替它。忙碌等待更恰当地捕获了消耗CPU资源的选择,希望可以正确检测到您的比赛结束状况,从而使结果保持一致。

通过放弃队列的头(Front),您不知道该客户端在承诺吸收它之前可能会使用多长时间(出队,原文如此,这并不是出队的意思)。这样,您的Front函数就只能是设计欠佳的队列实现的前沿。

从来没有很长一段时间。好的,不是永远,但是,它需要一个伴随函数(Absorb),该函数可以告诉我们,由于调用了相应的Front,因此队列头的吸收是队列头上的唯一操作。因此队列处于相同状态。如果不是,则必须向调用方退回故障,在此过程中,它必须回滚正在进行的任何操作以反映此故障。

好吧,不是永远不会,但是已经完成的一切只是将事务语义上移了一个层次,向设计者暗示也许设计有点欠缺。因此,您有一个无事务的队列。我们中有些人称其为增量