boost :: lockfree :: spsc_queue忙等待策略。是否有阻止流行音乐?

时间:2014-03-18 17:21:53

标签: c++ multithreading boost boost-thread lock-free

所以我使用boost::lockfree::spec_queue通过两个boost_threads在我的应用程序中运行两个对象的仿函数进行通信。

一切都很好,除了spec_queue::pop()方法是非阻塞的。即使队列中没有任何内容,它也会返回True或False。但是我的队列似乎总是返回True(问题#1)。我想这是因为我预先分配了队列。

typedef boost::lockfree::spsc_queue<q_pl, boost::lockfree::capacity<100000> > spsc_queue;

这意味着要有效地使用队列,我必须忙着等待不断使用100%cpu弹出队列。我宁愿不睡任意的时间。我已经在java中使用了其他队列,直到一个对象可用为止。可以用std ::或boost :: data结构来完成吗?

2 个答案:

答案 0 :(得分:9)

根据定义,无锁队列没有阻塞操作。

您如何在数据结构上同步?由于显而易见的原因,没有内部锁,因为这意味着所有客户端都需要在其上进行同步,使其成为您的祖父锁定并发队列。

的确,你必须自己设计一个等待功能。你如何做到这一点取决于你的用例,这可能是图书馆没有提供的用例(免责声明:我没有检查过,我也没有声称知道完整的文档)。

那你能做什么:

  • 正如您已经描述的那样,您可以在紧密循环中旋转。显然,如果你知道你的等待条件(队列非空)总是很快得到满足,你就会这样做。

  • 或者,以特定频率轮询队列(同时进行微睡眠)。调度好的频率是一门艺术:对于某些应用,100ms是最佳的,对于其他应用,潜在的100ms等待会破坏吞吐量。因此,改变并衡量您的性能指标(如果您的应用程序将部署在数据中心的多个核心上,请不要忘记功耗:)。

最后,你可以得到一个混合解决方案,旋转一定数量的迭代,并在没有任何东西到来的情况下采用(增加)间隔轮询。这将很好地支持突发高负载的服务器应用程序。

答案 1 :(得分:0)

使用信号量使生产者在队列满时进入休眠状态,使用另一个信号量使消费者在队列为空时休眠。 当队列既不是满也不是空时,sem_post和sem_wait操作是非阻塞的(在较新的内核中)

#include <semaphore.h>

template<typename lock_free_container>
class blocking_lock_free
{
public:
    lock_free_queue_semaphore(size_t n) : container(n)
    {
        sem_init(&pop_semaphore, 0, 0);
        sem_init(&push_semaphore, 0, n);
    }

    ~lock_free_queue_semaphore()
    {
        sem_destroy(&pop_semaphore);
        sem_destroy(&push_semaphore);
    }

    bool push(const lock_free_container::value_type& v)
    {
        sem_wait(&push_semaphore);
        bool ret = container::bounded_push(v);
        ASSERT(ret);
        if (ret)
            sem_post(&pop_semaphore);
        else
            sem_post(&push_semaphore); // shouldn't happen
        return ret;
    }

    bool pop(lock_free_container::value_type& v)
    {
        sem_wait(&pop_semaphore);
        bool ret = container::pop(v);
        ASSERT(ret);
        if (ret)
            sem_post(&push_semaphore);
        else
            sem_post(&pop_semaphore); // shouldn't happen
        return ret;
    }
private:
    lock_free_container container;
    sem_t pop_semaphore;
    sem_t push_semaphore;
};