我正在编写一个程序,在给定 A 和 B 矩阵的情况下执行高斯消去法。我首先获取除数和乘数,创建在 gauss 函数中执行的 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;
}
最佳答案
你有一个竞争条件(至少一个),你的代码没有正确使用它的条件变量。您可能可以通过修复后者来修复前者。此外,我怀疑您打算共享 gauss()
的局部变量 thread_count
,但没有共享没有链接的变量。
首先,竞争条件。考虑主线程:它启动其他三个线程,然后锁定互斥量并等待条件变量 condM
收到信号。但是假设所有线程都设法在主线程开始等待之前发出 condM
信号?条件变量操作是即时的——任何在 main()
等待它之前发生的 condM
信号都会丢失。
现在让我们换个话题来谈谈条件变量。作为the Linux manual for pthread_cond_wait()
说:
When using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed. Spurious wakeups from the
pthread_cond_timedwait()
orpthread_cond_wait()
functions may occur. Since the return frompthread_cond_timedwait()
orpthread_cond_wait()
does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.
换句话说,条件变量用于在给定条件变为真之前暂停线程操作。用抽象的术语来说,该条件始终是“该线程可以继续进行”,但这是在特定于上下文的术语中实现的。最重要的是,线程从等待中醒来的事实永远不会固有地表明条件为真;它仅仅表示新唤醒的线程应该检查条件是否为真。通常,线程还应在第一次等待之前进行检查,因为条件可能已经为真。
在伪代码中,它看起来像这样:
线程 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 谓词为假,因此有时线程确实会执行它们的等待。
现在考虑如何将其应用于 main()
中的竞争条件。 main()
如何知道是否等待 condM()
?某处需要有一个共享变量来回答它,并且它的等待必须以该变量的值为条件。任何允许主线程继续进行的线程都必须为变量和信号 condM
设置适当的值。主线程本身也应该根据需要设置变量,以表明它当时还没有准备好继续。
当然,您的其他 CV 用法也存在同样的问题。
关于c - pthreads C 程序在执行时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42257101/