我正在尝试实现单个生产者(主线程)和单个消费者(子线程从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;
}
是正确的方法吗?还是有更好的方法呢?
我遇到了一些库,例如
libevent
或libev
或boost::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/