所以,我正在为同时运行4个线程的类编写一个程序。我已经让程序运行得很好,除了它在运行时停止的事实。我不确定它是否与我设置pthread_cond_wait的方式有关,或者是否与其他内容相关。我已多次手动追踪该程序,无法找到解释。
这是我的代码:
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>
//#define TENP .1
//#define FIFTP .15
void *tenPercentA();
void *tenPercentB();
void *fiftPercentC();
void *fiftPercentD();
pthread_cond_t aPirate;
pthread_cond_t bPirate;
pthread_cond_t cPirate;
pthread_cond_t dPirate;
pthread_mutex_t mutex;
int pearls = 1000;
int main()
{
pthread_t tid;
pthread_setconcurrency(4);
pthread_create(&tid, NULL, (void *(*)(void *))tenPercentA, NULL);
pthread_create(&tid, NULL, (void *(*)(void *))tenPercentB, NULL);
pthread_create(&tid, NULL, (void *(*)(void *))fiftPercentC, NULL);
pthread_create(&tid, NULL, (void *(*)(void *))fiftPercentD, NULL);
pthread_exit(0);
}
void *tenPercentA(){
int totalA = 0;
double tempA = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempA = pearls * .1;
tempA = ceil(tempA);
totalA = totalA + tempA;
pearls = pearls - tempA;
printf("Pirate A stole %1.1f pearls.\n", tempA);
printf("Pirate A's total: %d\n", totalA);
sleep(1);
pthread_cond_broadcast (&bPirate);
pthread_cond_broadcast (&cPirate);
pthread_cond_broadcast (&dPirate);
tempA = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&aPirate, &mutex);
}
}
void *tenPercentB(){
int totalB = 0;
double tempB = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempB = pearls * .1;
tempB = ceil(tempB);
totalB = totalB + tempB;
pearls = pearls - tempB;
printf("Pirate B stole %1.1f pearls.\n", tempB);
printf("Pirate B's total: %d\n", totalB);
sleep(1);
pthread_cond_broadcast (&aPirate);
pthread_cond_broadcast (&cPirate);
pthread_cond_broadcast (&dPirate);
tempB = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&bPirate, &mutex);
}
}
void *fiftPercentC(){
int totalC = 0;
double tempC = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempC = pearls * .15;
tempC = ceil(tempC);
totalC = totalC + tempC;
pearls = pearls - tempC;
printf("Pirate C stole %1.1f pearls.\n", tempC);
printf("Pirate C's total: %d\n", totalC);
sleep(1);
pthread_cond_broadcast (&bPirate);
pthread_cond_broadcast (&aPirate);
pthread_cond_broadcast (&dPirate);
tempC = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&cPirate, &mutex);
}
}
void *fiftPercentD(){
int totalD = 0;
double tempD = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempD = pearls * .15;
tempD = ceil(tempD);
totalD = totalD + tempD;
pearls = pearls - tempD;
printf("Pirate D stole %1.1f pearls.\n", tempD);
printf("Pirate D's total: %d\n", totalD);
sleep(1);
pthread_cond_broadcast (&bPirate);
pthread_cond_broadcast (&cPirate);
pthread_cond_broadcast (&aPirate);
tempD = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&dPirate, &mutex);
}
}
这是运行时它的一些示例输出:
Pirate A stole 100.0 pearls.
Pirate A's total: 100
Pirate B stole 90.0 pearls.
Pirate B's total: 90
Pirate C stole 122.0 pearls.
Pirate C's total: 122
我唯一可以解释它的想法是,当CPU调度程序有两个线程准备好背靠背运行时,程序会卡住。例如(在调度队列中):A | B | C | C | D.有什么建议吗?
答案 0 :(得分:1)
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
<do some stuff>
} else {
print "all done";
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&bPirate, &mutex);
}
所以如果所有的盗版者都在pthread_condition_wait等待,那么当最后一个盗版者偷走了最后一颗珍珠时你可能会找到珍珠== 0并退出循环。现在你永远不会打印你所有完成的条件。并且你会在程序结束时没有打印任何东西而退出。
这就是你的程序停止而不打印任何内容的原因。
编辑:(以上情况仍属实,但目前看来不是问题) 来自http://linux.die.net/man/3/pthread_cond_wait:
它们应该被调用线程锁定的互斥锁或未定义的行为结果
调用这些函数以原子方式释放互斥锁
成功返回后,互斥锁将被锁定,并且应由调用线程
拥有
So what you want is:
pthread_mutex_lock(&mutex);
while (pearls > 0) {
<do your thing>
<signal other threads>
pthread_cond_wait(&mutex);
}
答案 1 :(得分:0)
您的计划中存在许多问题。
1.- pthread_cond_wait没有锁:就像dave已经指出的那样,你应该用互斥锁来调用它。否则你有未定义的行为(这总是很糟糕)。
示例:
pthread_mutex_lock(&mutex);
while (!conditionMet) {
//..
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
2.-访问非互斥保护变量:您正在访问线程中的变量pearls
,而不使用互斥锁保护访问权限(在while(pearls>0)
中) 。另一个线程可能正在写入它。虽然访问可能是原子的,但不能保证。
3.-在线程内退出(0)。 exit()导致正常程序终止。它猜测,这不是你想要的线程函数。只需使用return
退出该帖子。
4.- pthread_exit(0);在main()中。 pthread_exit()函数终止调用线程。在main结束时,您应该等待所有线程先终止。使用pthread_join
(每个线程需要一个pthread_t
)。然后正常返回以退出程序。
在进一步搜索之前,您应该先解决所有这些问题。