我正在尝试实现单个生产者(主线程)和单个消费者(子线程从Main派生)的问题,因此根据我的搜索,我得到了spsc_queue作为boost库提供的最佳无锁数据结构。现在从他们的示例代码中获取,消费者函数如下所示:

void consumer(void)
{
    int value;
    while (!done) {
        while (queue.pop(value))
            ++consumer_count;
    }

    while (queue.pop(value))
        ++consumer_count;
}


现在,可能发生了spsc_queue may remain empty for sometime等问题,为了避免繁忙的等待,我在如下代码中引入了sleep:

void consumer(void)
{
    int value;
    while (!done) {
        if (spsc_queue.empty())
        {
            cout << "Waiting for data....\n";
            this_thread::sleep_for (chrono::milliseconds(100));
        }
        else
        {
            while (spsc_queue.pop(value))
            {
                ++consumer_count;
            }
        }
    }

    while (spsc_queue.pop(value))
        ++consumer_count;
}


是正确的方法吗?还是有更好的方法呢?
我遇到了一些库,例如libeventlibevboost::asio::io_service-有人可以帮助我找出避免繁忙等待的最佳方法吗?

我担心的是性能,并且代码必须无锁且无等待(如果可能)。任何帮助,将不胜感激。

最佳答案

您的目标与您的要求不兼容。

wait-free:等待直到元素可用时已经排除此属性。

无锁:您的目标是在某个元素可用(即您要阻止)之前不做任何工作。同样,这与免等待和无锁矛盾。

你真正想要的是

if (spsc_queue.empty()) {
     doSomethingElse();
}


或者简单地,继续忙循环。

也许最接近您想要的是:

if (spsc_queue.empty()) {
    std::this_thread::yield();
}


它可以重新安排线程的时间,并让其他线程执行工作。但是,您正在放弃时间片,并且可能不会在25-100毫秒之前重新安排时间。

代码必须无锁的任何特定原因?由于队列为空的可能性似乎很高,所以为什么需要无锁代码?在这种情况下,您没有任何收获。

另一方面,如果您排空队列的可能性很低,那么繁忙的循环将随着时间摊销。无论如何,您都不会在繁忙的循环中花费很多时间,但是会尽可能快地删除您的元素(以偶尔的繁忙等待为代价)。

关于c++ - 使用spsc_queue避免在单一生产者单一消费者程序中忙于等待,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32568777/

10-11 22:51
查看更多