gpt4 book ai didi

c++ - Boost的无锁队列有可能丢元素吗?

转载 作者:行者123 更新时间:2023-11-30 02:31:44 24 4
gpt4 key购买 nike

我有一个单线程应用程序,它使用boost::lockfree::queue(来自Boost 1.57)。 (我使用队列的原因是它是多线程应用程序中也使用的库的一部分。)

队列似乎以某种方式丢失了元素。

使用队列的类行为如下:

  • 有两个单独的函数调用队列上的push。除了队列本身提供的内容之外,没有线程安全逻辑。
  • 有一个函数可以从队列中获取元素;它消耗 所有 元素,使用 while(my_queue.pop(temp_element)) 循环。此函数受互斥锁保护,以确保所有元素都发送给单个 消费者。但是,如果在一行中检测到两个重复元素(与==相比),则跳过第二个元素。

我观察到元素似乎无法通过系统持续传播,因此使用 std::atomic_uint,我创建了一些计数器来检查离开队列的警报数量是否与进入队列的数量相同它:

  • 两种推送方法中的每一种都有单独的计数器。我们将调用这些 pushed_method1pushed_method2
  • “已处理”元素和“已跳过”元素有单独的计数器。我们称这些为 consumedskipped。在循环中,它们更新如下(重命名变量,并在 [square brackets] 中使用描述性伪代码):

    ElementType previous{[ initialize in invalid state ]};
    while (my_queue.pop(temp_element))
    {
    if (! [ check if `previous` is valid ]
    || previous != temp_element)
    {
    [ ... log a message ]
    [ ... insert the element into a vector to be returned ]

    ++consumed;
    }
    else
    {
    // ... log a message

    ++skipped;
    }

    previous = temp_element;
    }

在循环之后,我检查计数器和队列的状态并进行健全性检查:

auto postconsume_pushed_method1 = pushed_method1.load();
auto postconsume_pushed_method2 = pushed_method2.load();
auto all_consumed = my_queue.empty();

assert(
!all_consumed
|| postconsume_pushed_method1 + postconsume_pushed_method2
== consumed + skipped);

这个断言通常会通过——但在我的单线程应用中它有时会失败。 (它有时也会在多线程情况下失败,但我希望关注单线程情况以简化问题。)

在多线程的情况下,我可以想象操作被重新排序,以便在 .empty() 检查之后发生一个或多个 load ,但我希望情况并非如此,因为我希望 std::atomicboost::lockfree 为这类事情包含内存栅栏。

但是,在单线程情况下,这应该无关紧要,因为当应用程序运行时,元素绝不推送执行“consume”方法,并且警报队列在循环之后应该始终为空(因为循环不会中断,直到 pop 返回 false).

我是不是误会了什么?我的逻辑有错误吗?我是否有可能在 boost::lockfree::queue 中发现错误?

最佳答案

队列是无锁的,因此 push 不会在队列满时阻塞。

lockfree::queue::push 返回一个 bool 值,指示元素是否已进入队列。当队列已满时,push 返回 false,因此您可能想检查一下这种情况。

关于c++ - Boost的无锁队列有可能丢元素吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37281969/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com