首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SPSC无原子无锁队列

SPSC无原子无锁队列
EN

Stack Overflow用户
提问于 2014-11-26 00:20:48
回答 1查看 2K关注 0票数 3

我的记录器在SPSC队列下面。

它肯定不是一个通用的SPSC无锁队列。

然而,考虑到关于它将如何使用、目标体系结构等的一系列假设,以及一些可以接受的折衷(我将在下面详细介绍这些权衡),我的问题基本上是,它是否安全/是否有效?

  • 它将只用于x86_64体系结构,因此对uint16_t的写入将是原子化的。
  • 只有生产者更新tail
  • 只有使用者更新head
  • 如果生产者读取head的旧值,那么队列中的空间将比实际少,这在所使用的上下文中是一个可接受的限制。
  • 如果使用者读取tail的旧值,那么队列中等待的数据似乎比实际少,这也是一个可以接受的限制。

上述限制是可以接受的,因为:

  • 使用者可能不会立即获得最新的tail,但最终将到达最新的tail,并将记录排队的数据。
  • 生产者可能不会立即得到最新的head,所以队列看起来比实际的更满。在我们的负载测试中,我们已经发现了我们记录的数量与队列的大小,以及记录器排出队列的速度,这个限制没有影响-队列中总是有空间。

最后一点,必须使用volatile来防止每个线程只读取的变量被优化。

我的问题:

  • 这个逻辑正确吗?
  • 队列线程安全吗?
  • volatile足够了吗?
  • volatile有必要吗?

My队列:

代码语言:javascript
复制
class LogBuffer
{
public:
    bool is_empty() const { return head_ == tail_; }
    bool is_full()  const { return uint16_t(tail_ + 1) == head_; }
    LogLine& head()       { return log_buffer_[head_]; }
    LogLine& tail()       { return log_buffer_[tail_]; }
    void advance_head()   { ++head_; }
    void advance_hail()   { ++tail_; }
private:
    volatile uint16_t tail_ = 0;     // write position
    LogLine log_buffer_[0xffff + 1]; // relies on the uint16_t overflowing
    volatile uint16_t head_ = 0;     // read position
};
EN

回答 1

Stack Overflow用户

发布于 2014-11-26 00:37:14

这个逻辑正确吗?

是。

队列线程安全吗?

不是的。

挥发性足够了吗?不稳定是必要的吗?

不对两个人来说。易失性不是使任何变量线程安全的神奇关键字。您仍然需要为索引使用原子变量或内存屏障,以确保在生成或使用项时内存排序是正确的。

具体来说,在您为队列生成或使用一个项之后,您需要发出一个内存屏障,以保证其他线程将看到这些更改。当您更新原子变量时,许多原子库将为您完成此操作。

顺便说一句,使用"was_empty“而不是"is_empty”来明确它的功能。此调用的结果是时间上的一个实例,它可能在您对其值进行操作时发生了更改。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27139260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档