gpt4 book ai didi

C++ 多线程、简单的消费者/生产者线程、后进先出、通知、计数器

转载 作者:行者123 更新时间:2023-11-30 03:03:17 27 4
gpt4 key购买 nike

我是多线程编程的新手,我想实现以下功能。

  1. 有 2 个线程,生产者和消费者。
  2. 消费者仅处理最新值,即后进先出 (LIFO)。
  3. 生产者有时会以比消费者更快的速度产生新值(value)过程。例如,生产者可能会在 1 中生成 2 个新值毫秒,但消费者大约需要 5 毫秒来处理。
  4. 如果消费者在处理旧值的过程中收到一个新值值,没有必要中断。换句话说,消费者将完成当前首先执行,然后开始执行最新值。

这是我的设计过程,如有错误请指正。

  1. 不需要队列,因为只有最新的值由消费者处理。
  2. 生产者发送的通知是否自动排队???
  3. 我会改用计数器。
  4. ConsumerThread() 最后检查计数器,以确保生产者不会产生新的值(value)。
  5. 但是如果生产者在消费者之前生成新值会发生什么进入休眠(),但在检查计数器之后???

这是一些伪代码。

boost::mutex mutex;
double x;

void ProducerThread()
{
{
boost::scoped_lock lock(mutex);
x = rand();
counter++;
}
notify(); // wake up consumer thread
}

void ConsumerThread()
{
counter = 0; // reset counter, only process the latest value

... do something which takes 5 milli-seconds ...

if (counter > 0)
{
... execute this function again, not too sure how to implement this ...
}
else
{
... what happen if producer generates a new value here??? ...
sleep();
}
}

谢谢。

最佳答案

如果我没有正确理解你的问题,对于你的特定应用程序,消费者只需要处理生产者提供的最新可用值。换句话说,因为消费者跟不上生产者,值(value)下降是可以接受的。

如果是这样,那么我同意您可以不用排队而使用柜台就可以离开。但是,共享计数器和值变量将需要原子访问。

您可以使用 boost::condition_variable向消费者发出新值已准备就绪的通知。这是一个完整的例子;我会让评论做解释。

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>

boost::mutex mutex;
boost::condition_variable condvar;
typedef boost::unique_lock<boost::mutex> LockType;

// Variables that are shared between producer and consumer.
double value = 0;
int count = 0;

void producer()
{
while (true)
{
{
// value and counter must both be updated atomically
// using a mutex lock
LockType lock(mutex);
value = std::rand();
++count;

// Notify the consumer that a new value is ready.
condvar.notify_one();
}

// Simulate exaggerated 2ms delay
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
}
}

void consumer()
{
// Local copies of 'count' and 'value' variables. We want to do the
// work using local copies so that they don't get clobbered by
// the producer when it updates.
int currentCount = 0;
double currentValue = 0;

while (true)
{
{
// Acquire the mutex before accessing 'count' and 'value' variables.
LockType lock(mutex); // mutex is locked while in this scope
while (count == currentCount)
{
// Wait for producer to signal that there is a new value.
// While we are waiting, Boost releases the mutex so that
// other threads may acquire it.
condvar.wait(lock);
}

// `lock` is automatically re-acquired when we come out of
// condvar.wait(lock). So it's safe to access the 'value'
// variable at this point.
currentValue = value; // Grab a copy of the latest value
// while we hold the lock.
}

// Now that we are out of the mutex lock scope, we work with our
// local copy of `value`. The producer can keep on clobbering the
// 'value' variable all it wants, but it won't affect us here
// because we are now using `currentValue`.
std::cout << "value = " << currentValue << "\n";

// Simulate exaggerated 5ms delay
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
}
}

int main()
{
boost::thread c(&consumer);
boost::thread p(&producer);
c.join();
p.join();
}

附录

我最近在思考这个问题,并意识到这个解决方案虽然可行,但并不是最优的。您的生产者使用所有 CPU 只是为了丢弃一半的计算值。

我建议您重新考虑您的设计并在生产者和消费者之间使用有界阻塞队列。这样的队列应该具有以下特点:

  • 线程安全
  • 队列有固定大小(有界)
  • 如果消费者想要弹出下一个项目,但队列为空,则操作将被阻塞,直到生产者通知项目可用。
  • 生产者可以检查是否有空间来插入另一个项目并阻塞直到空间可用。

使用这种类型的队列,您可以有效地降低生产者的速度,使其不会超过消费者。它还确保生产者不会浪费 CPU 资源来计算将被丢弃的值。

库,例如 TBBPPL提供并发队列的实现。如果您想尝试自己使用 std::queue(或 boost::circular_buffer)和 boost::condition_variable,请查看这位博主的example .

关于C++ 多线程、简单的消费者/生产者线程、后进先出、通知、计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9450884/

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