在线程上需要紧急帮助:这里的目标是separtemask将获取每个图像并分离不同的轮廓,并且对于图像中的每个轮廓,它将调用handleobject线程。所以每个for循环都会调用handeobject线程。但是,需要在每个线程中传递对象索引变量。但是只传递了objectndex的最后一个值,这是因为speratemask函数循环并重新生成obj.objindx的值,并且只有obj.objindx的最后一个值是 传递给所有线程。无论如何都要传递每个对象索引 handleobject中的值。如果我们取消注释pthread_join(tid [objectIndex],NULL),代码运行正常;但它不会给出一个parralel程序
void separateMask(IplImage *maskImg)
{
for(r = contours; r != NULL; r = r->h_next)
{
cvSet(objectMaskImg, cvScalarAll(0), NULL);
CvScalar externalColor = cvScalarAll(0xff);
CvScalar holeColor = cvScalarAll(0x00);
int maxLevel = -1;
int thinkness = CV_FILLED;
int lineType = 8; /* 8-connected */
cvDrawContours(objectMaskImg, r, externalColor, holeColor, maxLevel, thinkness,lineType, cvPoint(0,0));;
obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
obj.objectMaskImg1[objectIndex]=objectMaskImg;
obj.objindx=objectIndex;
obj.intensityOut1=intensityOut;
obj.tasOut1=tasOut;
pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);
//pthread_join(tid[objectIndex],NULL);
printf("objectindx %d\n",obj.objindx);
objectIndex++;
}
// cvReleaseImage(&objectMaskImg);
//cvReleaseMemStorage(&storage);
printf("Exitng Separatemask\n");
}
void* handleObject(void *arg)
{
int i, j;
handle *hndl;
hndl=(handle *) malloc(sizeof(handle));
hndl=(handle*)arg;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
IplImage *pImg;
float statistics_ratio[3][9];
pthread_t tid3;
tas3 tas2;
pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
if(pImg == NULL)
{
fprintf(stderr, "Fail to load image %s\n", "tiff file");
return ;
}
tas2.pImg1=pImg;
printf("tst%d\n",hndl->objindx);
tas2.x=hndl->objindx;
tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
tas2.statistics_ratio[3][9]=statistics_ratio[3][9];
double mean = average_intensity(pImg, tas2.objectMaskImg1);
int total = total_white(pImg, tas2.objectMaskImg1);
pthread_mutex_unlock(&lock);
printf("Exiting handle object thread_id %d\n\n", pthread_self());
}
答案 0 :(得分:2)
此功能似乎有问题
void* handleObject(void *arg)
首先
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
这是一个本地创建的互斥锁 - 但在线程函数中创建了WITH。所以你锁定它,但因为没有别的东西可以看到互斥锁,为什么你需要它?如果没有其他线程可以看到它,它不提供同步功能。 其次
float statistics_ratio[3][9];
pthread_t tid3;
tas3 tas2;
pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
if(pImg == NULL){
fprintf(stderr, "Fail to load image %s\n", "tiff file");
return ;
}
tas2.pImg1=pImg;
printf("tst%d\n",hndl->objindx);
tas2.x=hndl->objindx;
tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
tas2.statistics_ratio[3][9]=statistics_ratio[3][9];
您创建一个本地未初始化的2d浮点数组statistics_ratio
,不执行任何操作,然后将其分配给另一个本地创建的对象成员。这似乎没有意义,另一个pthread实例tid3
的声明也是如此。
这并不重要,因为没有其他任何东西可以看到该线程,但是如果pImg == NULL
没有先解锁互斥锁,则从此函数内部返回。
很难理解为什么你的代码不起作用或它的意图,但也许上面提到的事情可能会有所帮助。您正在线程函数中创建许多未使用的局部变量。我不确定你是否需要其中一些是全局的 - 尤其是互斥体(如果确实你需要一个)。
答案 1 :(得分:1)
我认为您最初的问题是您正在重复使用您传递给创建的线程的obj
结构,因此您将拥有数据竞争,其中刚创建的线程将读取已被数据覆盖的信息打算用于另一个主题。
创建线程的循环具有以下结构:
for(r = contours; r != NULL; r = r->h_next)
{
// initialize obj with information for the thread
// ...
// create a thread and pass it a pointer to obj
pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);
// some other bookkeeping
}
由于您在下一次循环迭代时立即重新初始化obj,谁知道线程函数将获得什么数据?这就是为什么如果你在创建它之后加入线程就行了 - obj
结构保持稳定,因为循环阻塞直到线程完成。
将循环更改为:
for(r = contours; r != NULL; r = r->h_next)
{
// instead of using `obj`, allocate a struct using malloc
handle* threaddata = malloc(sizeof(handle); // note: I'm not sure if `handle` is the right type
// initialize *threaddata with information for the thread
// ...
// create a thread and pass it the threaddata pointer
pthread_create(&tid[objectIndex],NULL,handleObject,threaddata);
// some other bookkeeping
}
然后free()
线程函数完成之后的数据(即,线程创建代码创建并初始化数据块,然后将其所有权传递给线程)。
请注意,这可能不像通常那样简单,因为看起来你的obj
结构中已经有一些每线程信息(objectMaskImg1
元素看起来像一个数组吧每个元素都用于单独的线程)。因此,您可能还需要对数据结构进行一些重构。
最后,还有其他一些彻头彻尾的错误,例如立即覆盖指向malloc()分配的块的指针:
obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
obj.objectMaskImg1[objectIndex]=objectMaskImg;
和
hndl=(handle *) malloc(sizeof(handle));
hndl=(handle*)arg;
除了数学家1975(http://stackoverflow.com/a/11460092/12711)提到的handleObject()
线程函数中毫无意义地使用互斥锁。
线程函数中的相当一部分代码(复制或尝试在本地复制数据,互斥锁)似乎是为了尝试修复问题而没有真正理解问题所在的东西。我认为你真的需要了解各种数据存在的位置,如何复制它(而不仅仅是复制指针),以及如何管理数据的所有权。