C++ 11非阻塞生产者/消费者

non*_*gon 8 multithreading producer-consumer c++11

我有一个C++ 11应用程序,它具有生成数据的高优先级线程,以及一个消耗它的低优先级线程(在我的情况下,将其写入磁盘).我想确保高优先级的生产者线程永远不会被阻止,即它只使用无锁算法.

使用无锁队列,我可以从生产者线程将数据推送到队列,并从消费者线程中轮询它,从而实现上述目标.我想修改我的程序,以便消费者线程在非活动状态而不是轮询时阻塞.

似乎C++ 11条件变量可能对阻塞使用者线程很有用.有人能告诉我一个如何使用它的例子,同时避免消费者睡觉时数据仍在队列中吗?更具体地说,我想确保在生产者将最后一个项目推入队列后,消费者总是在某个有限的时间内被唤醒.生产者保持非阻塞也很重要.

Jon*_*ely 2

看起来 C++11 条件变量可能有助于阻止使用者线程。谁能向我展示一个如何使用它的示例,同时避免消费者在数据仍在队列中的情况下睡觉的可能性?

要使用条件变量,您需要一个互斥体和一个条件。在您的情况下,条件将是“队列中有可用数据”。由于生产者将使用无锁更新来生产工作,因此消费者必须使用相同形式的同步来消费工作,因此互斥锁实际上不会用于同步,并且仅由消费者线程需要,因为没有等待条件变量的其他方式。

// these variables are members or otherwise shared between threads
std::mutex m_mutex;
std::condition_variable m_cv;
lockfree_queue m_data;

// ...

// in producer thread:
while (true)
{
  // add work to queue
  m_data.push(x);
  m_cv.notify_one();
}

// in consumer thread:
while (true)
{
  std::unique_lock<std::mutex> lock(m_mutex);
  m_cv.wait(lock, []{ return !m_data.empty(); });
  // remove data from queue and process it
  auto x = m_data.pop();
}
Run Code Online (Sandbox Code Playgroud)

wait仅当等待之前队列为空时,条件变量才会阻塞调用。条件变量可能会被虚假唤醒,或者因为它是由生产者通知的,但在任何一种情况下,wait如果队列非空,则只会从调用中返回(而不是再次休眠)。这是通过使用condition_variable::wait带有谓词的重载来保证的,因为条件变量总是为您重新检查谓词。

由于互斥锁仅由消费者线程使用,因此实际上它可能是该线程的本地线程(只要您只有一个消费者,如果有多个消费者,它们都需要共享相同的互斥锁以等待相同的 condvar)。