【发布时间】:2015-07-08 13:31:15
【问题描述】:
更新:我在下面的回答中提供了问题的原因及其解决方案。
我想为图像处理任务实现基于生产者-消费者方法的多线程。对于我来说,Producer 线程应该抓取图像并将它们放入container,而消费者线程应该从Container 线程中提取图像。我认为我应该使用queue 来实现container。
我想按照SO answer 中的建议使用以下代码。但我对container 的实现以及将传入的图像放入Producer 线程中感到非常困惑。
问题:第一个consumer thread显示的图片不包含完整的数据。而且,第二个consumer thread 从不显示任何图像。可能是由于某些竞争情况或锁定情况,第二个线程根本无法访问队列的数据。我已经尝试过使用Mutex。
#include <vector>
#include <thread>
#include <memory>
#include <queue>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
Mutex mu;
struct ThreadSafeContainer
{
queue<unsigned char*> safeContainer;
};
struct Producer
{
Producer(std::shared_ptr<ThreadSafeContainer> c) : container(c)
{
}
void run()
{
while(true)
{
// grab image from camera
// store image in container
Mat image(400, 400, CV_8UC3, Scalar(10, 100,180) );
unsigned char *pt_src = image.data;
mu.lock();
container->safeContainer.push(pt_src);
mu.unlock();
}
}
std::shared_ptr<ThreadSafeContainer> container;
};
struct Consumer
{
Consumer(std::shared_ptr<ThreadSafeContainer> c) : container(c)
{
}
~Consumer()
{
}
void run()
{
while(true)
{
// read next image from container
mu.lock();
if (!container->safeContainer.empty())
{
unsigned char *ptr_consumer_Image;
ptr_consumer_Image = container->safeContainer.front(); //The front of the queue contain the pointer to the image data
container->safeContainer.pop();
Mat image(400, 400, CV_8UC3);
image.data = ptr_consumer_Image;
imshow("consumer image", image);
waitKey(33);
}
mu.unlock();
}
}
std::shared_ptr<ThreadSafeContainer> container;
};
int main()
{
//Pointer object to the class containing a "container" which will help "Producer" and "Consumer" to put and take images
auto ptrObject_container = make_shared<ThreadSafeContainer>();
//Pointer object to the Producer...intialize the "container" variable of "Struct Producer" with the above created common "container"
auto ptrObject_producer = make_shared<Producer>(ptrObject_container);
//FIRST Pointer object to the Consumer...intialize the "container" variable of "Struct Consumer" with the above created common "container"
auto first_ptrObject_consumer = make_shared<Consumer>(ptrObject_container);
//SECOND Pointer object to the Consumer...intialize the "container" variable of "Struct Consumer" with the above created common "container"
auto second_ptrObject_consumer = make_shared<Consumer>(ptrObject_container);
//RUN producer thread
thread producerThread(&Producer::run, ptrObject_producer);
//RUN first thread of Consumer
thread first_consumerThread(&Consumer::run, first_ptrObject_consumer);
//RUN second thread of Consumer
thread second_consumerThread(&Consumer::run, second_ptrObject_consumer);
//JOIN all threads
producerThread.join();
first_consumerThread.join();
second_consumerThread.join();
return 0;
}
【问题讨论】:
-
您是否考虑过使用带有互斥锁的队列?我在多个项目中使用这种方法,效果很好。
-
许多框架都支持线程池类。你确定要自己做吗?
-
@dumbak:我在多线程方面没有任何经验,所以我愿意接受任何建议。
-
@skm 我下面的回答与 dumbak 的建议相同。如果您查看我的 github 存储库中的代码,您应该会找到使用队列和互斥体解决方案的简单消费者生产者所需的一切。
-
@qzcx:谢谢,我去看看。
标签: c++ multithreading opencv image-processing computer-vision