【发布时间】:2016-03-22 15:57:03
【问题描述】:
在尝试了解如何处理无锁代码的过程中,我尝试编写一个单一消费者/单一生产者无锁队列。和往常一样,我检查了论文、文章和代码,特别是考虑到这是一个有点微妙的主题。
所以,我在 Folly 库中偶然发现了这种数据结构的实现,可以在这里找到: https://github.com/facebook/folly/blob/master/folly/ProducerConsumerQueue.h
正如我看到的每个无锁队列,这个似乎使用循环缓冲区,所以我们有两个std::atomic<unsigned int> 变量:readIndex_ 和writeIndex_。 readIndex_ 表示我们将读取的下一个索引,writeIndex_ 表示我们将写入的下一个索引。看起来很简单。
所以,乍一看,这个实现看起来很干净而且很简单,但我发现有一点很麻烦。事实上,isEmpty()、isFull() 或 guessSize() 等一些函数正在使用 std::memory_order_consume 来检索索引的值。
老实说,我真的不知道它们的用途是什么。不要误会我的意思,我知道 std::memory_order_consume 在通过原子指针进行依赖的经典案例中的使用,但是在这里,我们似乎没有携带任何依赖!我们只是得到索引,无符号整数,我们不创建依赖项。在这种情况下,对我来说,std::memory_order_relaxed 是等价的。
但是,我不相信自己比那些设计此代码的人更了解内存排序,因此我在这里问这个问题。有什么我遗漏或误解的吗?
提前感谢您的回答!
【问题讨论】:
-
很少有
std::memory_order_relaxed真正发挥作用的情况。你真的需要一个能够撕裂读/写的芯片。一个例子是 x86 在处理未对齐的数据时,但你不应该这样做。我之所以这么说,是因为如果您认为需要memory_order_relaxed,您可能不了解其用法。您是否试图防止读取/写入撕裂? -
@SideEffects:我同意你的看法。没有后续的内存访问依赖于这些函数中的索引值,所以我看不出
std::memory_order_consume怎么可能贡献任何有用的东西。作者的电子邮件地址位于文件顶部;也许尝试给他们发电子邮件? (如果你这样做,请在此处添加更新或答案。我很好奇我们是否遗漏了什么。) -
@SergeyA 是的,我在这里可能有点不清楚。我想说的是,我相信消耗内存排序至少对我来说没有添加任何有用的东西。但是,是的,我可能想澄清这一点,谢谢!
-
@Nemo 在给他们发电子邮件之前,我会稍等片刻,以便在继续之前尝试获得尽可能多的反馈。感谢您的评论!
标签: c++ multithreading c++11 atomic lock-free