我正在编写一个程序,在给定A和B矩阵的情况下执行高斯消元法。我首先抓取除数和乘数,创建以高斯函数执行的pthreads,它在单个“列”上执行操作。然后我调用main生成新的除数和乘数,并通过相同的线程传回给另一轮操作。使用条件pthread变量来完成此任务。
代码一直挂起,直到我创建一个断点然后继续并完成。不知道是什么阻碍了它。可以使用一些帮助。
#include <stdio.h>
#include <pthread.h>
//Need one mutex variable and two condition variables (one c var for
//communicating between threads, and one c var for communicating with main).
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t condM = PTHREAD_COND_INITIALIZER;
float arr[3][4] = {{2,-3,1, -22},{7,9,-3, 14},{6,7,2,91}};
float mults[3];
float divisor;
int num_items = 3;
void* gauss(void *mine)
{
int thread_count=0;
int x = *((int *)mine);
for(int i=0;i<num_items;i++)
{
/*do something*/
arr[i][x] = arr[i][x] / divisor;
for(int k=0;k<num_items;k++){
if(k!=i)
arr[k][x] -= mults[k] * arr[i][x];
}
/*lock || wait || signal*/
pthread_mutex_lock(&mut);
thread_count++;
if(thread_count < num_items)
pthread_cond_wait(&cond,&mut);
else
{
pthread_cond_signal(&condM);
pthread_cond_wait(&cond,&mut);
thread_count = 0;
}
pthread_mutex_unlock(&mut);
}
return NULL;
}
int main(int argc, const char * argv[]) {
int i, j;
pthread_t threadr[num_items+1]; /*thread id array */
int is[num_items+1];
printf("Test");
// /*input num items*/
// printf("input the number of items ");
// scanf("%d",&num_items);
//
// /*input A array*/
// printf("input A array\n");
// for(i=0;i<num_items;i++)
// for(j=0;j<num_items;j++)
// scanf("%f",&arr[i][j]);
//
// /*input B array*/
// printf("input B array\n");
// for(i=0;i<num_items;i++)
// scanf("%f",&arr[i][num_items]);
/*grab first divisor & multipliers*/
divisor = arr[0][0];
for(i=0;i<num_items;i++)
{
mults[i] = arr[i][0];
}
for(i=0;i<num_items+1;i++)
{
is[i]=i;
if(pthread_create(&threadr[i],NULL,gauss,(void *)&is[i]) != 0)
perror("Pthread_create fails");
}
for(i=1;i<num_items;i++)
{
pthread_mutex_lock(&mut);
pthread_cond_wait(&condM,&mut);
divisor = arr[i][i];
for(j=0;j<num_items;j++)
{
mults[j] = 1;
if(j != i)
mults[j] = arr[j][i];
}
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
}
printf("The X values are:\n");
for(i=0;i<num_items; i++) {
printf("%0.3f \n", arr[i][num_items]);
}
/*wait for all threads*/
for(i=0;i<num_items+1; i++)
if (pthread_join(threadr[i],NULL) != 0)
perror("Pthread_join fails");
return 0;
}
答案 0 :(得分:0)
您有竞争条件(至少一个),并且您的代码未正确使用其条件变量。您可以通过修复后者来修复前者。另外,我怀疑您打算共享gauss()
的本地变量thread_count
,但不共享没有链接的变量。
首先,竞争条件。考虑主线程:它启动其他三个线程,然后锁定互斥锁并等待条件变量condM
发出信号。但是假设线程都在主线程开始等待之前设法发出condM
信号?条件变量操作是立即的 - 在condM
等待它之前发生的main()
的任何信号都将丢失。
现在让我们转变谈论条件变量。正如the Linux manual for pthread_cond_wait()
所说:
使用条件变量时,总会有一个布尔谓词,涉及与每个条件等待关联的共享变量,如果线程应该继续,则为true。可能会发生
pthread_cond_timedwait()
或pthread_cond_wait()
函数的虚假唤醒。由于pthread_cond_timedwait()
或pthread_cond_wait()
的返回并不意味着该谓词的值,因此应在返回时重新评估谓词。
换句话说,条件变量用于挂起线程操作,等待给定条件变为true。从抽象的角度来看,这个条件总是“这个线程可以继续”,但这是在特定于上下文的术语中实现的。最重要的是,一个线程从等待中醒来的事实从来没有传达过条件是真的;它只是表明新唤醒的线程应检查条件是否为真。通常,线程也应该在第一次等待之前检查,因为条件可能已经为真。
在伪代码中,看起来像这样:
主题1:
lock mutex;
loop
if is_ok_to_proceed then exit loop;
wait on condition variable;
end loop
// ... maybe do mutex-protected work ...
unlock mutex
主题2:
lock mutex
// ... maybe do mutex-protected work ...
is_ok_to_proceed = true;
signal condition variable;
unlock mutex
一般来说,在其他地方还有(互斥保护的)代码会使CV谓词为false,因此有时线程确实会执行等待。
现在考虑一下如何适用于main()
中的竞争条件。 main()
如何知道是否等待condM()
?需要有一个共享变量来回答它,并且它的等待必须以该变量的值为条件。任何意味着允许主线程继续运行的线程都必须为变量设置适当的值并发出信号condM
。主线程本身也应该根据需要设置变量,以表明当时不准备好继续进行。
当然,您的其他简历使用也会遇到同样的问题。