具有两个线程,一个是产品数据,另一个是过程数据。
数据不仅是int
或float
,而且是一个复杂的对象。就我而言,它是OpenCV Mat
(图片)。
如果第一个线程仅创建了图像大小的一半,而第二个线程读取了它,是否将获得图像的一半大小?图片会损坏吗?
int main(int argc, char *argv[])
{
cv::Mat buffer;
cv::VideoCapture cap;
std::mutex mutex;
cap.open(0);
std::thread product([](cv::Mat& buffer, cv::VideoCapture cap, std::mutex& mutex){
while (true) { // keep product the new image
cv::Mat tmp;
cap >> tmp;
//mutex.lock();
buffer = tmp.clone();
//mutex.unlock();
}
}, std::ref(buffer), cap, std::ref(mutex));
product.detach();
int i;
while (true) { // process in the main thread
//mutex.lock();
cv::Mat tmp = buffer;
//mutex.unlock();
if(!tmp.data)
std::cout<<"null"<<i++<<std::endl;
else {
//std::cout<<"not null"<<std::endl;
cv::imshow("test", tmp);
}
if(cv::waitKey(30) >= 0) break;
}
return 0;
}
我是否需要在读写周围添加互斥体以确保图像不被破坏?像这样:
int main(int argc, char *argv[])
{
cv::Mat buffer;
cv::VideoCapture cap;
std::mutex mutex;
cap.open(0);
std::thread product([](cv::Mat& buffer, cv::VideoCapture cap, std::mutex& mutex){
while (true) { // keep product the new image
cv::Mat tmp;
cap >> tmp;
mutex.lock();
buffer = tmp.clone();
mutex.unlock();
}
}, std::ref(buffer), cap, std::ref(mutex));
product.detach();
while (true) { // process in the main thread
mutex.lock();
cv::Mat tmp = buffer;
mutex.unlock();
if(!tmp.data)
std::cout<<"null"<<std::endl;
else {
std::cout<<"not null"<<std::endl;
cv::imshow("test", tmp);
}
}
return 0;
}
有关
答案 0 :(得分:1)
一旦一个线程修改了一个对象,而另一个线程潜在地并发访问了同一对象的值,您将拥有一个race condition并且行为是不确定的。是的,可能会发生。而且,由于我们在这里谈论的对象是整个图像缓冲区,因此几乎可以肯定会发生。是的,您将需要使用适当的同步来防止它发生。
根据您的描述,似乎您基本上处于一种情况,其中一个线程正在生成某些图像,而另一个线程必须等待该图像准备就绪。在这种情况下,您应该问自己的第一个问题是:如果第二个线程在第一个线程完成工作之前无法开始工作,那么您在这里使用第二个线程究竟能获得什么呢?如果仍有足够的工作使两个线程可以并行执行所有操作,那么您很可能不仅希望在这里使用简单的互斥锁,还应该使用诸如condition variable或barrier…