C 程序在线程期间停止

C 程序在线程期间停止,c,multithreading,unix,C,Multithreading,Unix,所以,我正在为同时运行4个线程的类编写一个程序。我已经让程序运行得很好,除了它在运行时停止之外。我不确定这是否与我设置pthread_cond_wait的方式有关,或者是其他原因。我已经用手摸过这个程序好几次了,都找不到解释 这是我的代码: #include <stdio.h> #include <pthread.h> #include <math.h> #include <stdlib.h> //#define TENP .1 //#defin

所以,我正在为同时运行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);
        }

}
我唯一能解释这一点的想法是,当CPU调度程序有两个线程准备背靠背运行时,程序会被卡住。例如(在计划队列中):A | B | C | C | D.有什么建议吗?

while(pearls>0){
 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_mutex_lock(&mutex); 如果(珍珠>0){ }否则{ 打印“全部完成”; } pthread_mutex_unlock(&mutex); pthread_cond_wait(&bPirate,&mutex); }
因此,如果所有海盗都在pthread_condition_wait等待,那么当最后一个海盗偷走最后一个珍珠时,您可能会发现珍珠==0并退出循环。现在,您将永远无法打印“全部完成”条件。在程序结束时,您将在没有打印任何内容的情况下退出

这就是为什么你的程序停止并且不打印任何东西

编辑:(以上仍然正确,但不是您目前看到的问题) 发件人:

调用它们时,应使用被调用线程锁定的互斥锁或未定义的行为结果

这些函数原子地释放互斥

成功返回后,互斥锁应已被锁定,并由调用线程拥有

那么您想要的是:
pthread_mutex_lock(&mutex);
而(珍珠>0){
pthread_cond_wait(&mutex);
}
while(pearls>0){
pthread_mutex_lock(&mutex);
如果(珍珠>0){
}否则{
打印“全部完成”;
}                
pthread_mutex_unlock(&mutex);
pthread_cond_wait(&bPirate,&mutex);
}
因此,如果所有海盗都在pthread_condition_wait等待,那么当最后一个海盗偷走最后一个珍珠时,您可能会发现珍珠==0并退出循环。现在,您将永远无法打印“全部完成”条件。在程序结束时,您将在没有打印任何内容的情况下退出

这就是为什么你的程序停止并且不打印任何东西

编辑:(以上仍然正确,但不是您目前看到的问题) 发件人:

调用它们时,应使用被调用线程锁定的互斥锁或未定义的行为结果

这些函数原子地释放互斥

成功返回后,互斥锁应已被锁定,并由调用线程拥有

那么您想要的是:
pthread_mutex_lock(&mutex);
而(珍珠>0){
pthread_cond_wait(&mutex);
}

您的程序中存在许多问题

1.-pthread\u cond\u wait without lock:就像dave已经指出的那样,您应该在互斥锁锁定的情况下调用它。否则,您会有未定义的行为(这总是不好的)

例如:

pthread_mutex_lock(&mutex);
while (!conditionMet) {
  //..
  pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
2.-访问非互斥保护变量:您正在线程中访问变量
pearls
,而不使用互斥保护访问(在
中,而(pearls>0)
)。另一个线程可能正在写入它。虽然访问可能是原子的,但不能保证

3.-线程内部退出(0)。exit()导致正常程序终止。我猜,这不是你想要的线程函数。只需使用
return
退出线程

4.-pthread_退出(0);在main()中。pthread_exit()函数终止调用线程。在main的末尾,您应该等待所有线程首先终止。使用
pthread\u join
(每个线程需要一个
pthread\u t
)。然后正常返回以退出程序


在进一步搜索之前,您应该先修复所有这些问题

您的程序中存在许多问题

1.-pthread\u cond\u wait without lock:就像dave已经指出的那样,您应该在互斥锁锁定的情况下调用它。否则,您会有未定义的行为(这总是不好的)

例如:

pthread_mutex_lock(&mutex);
while (!conditionMet) {
  //..
  pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
2.-访问非互斥保护变量:您正在线程中访问变量
pearls
,而不使用互斥保护访问(在
中,而(pearls>0)
)。另一个线程可能正在写入它。虽然访问可能是原子的,但不能保证

3.-线程内部退出(0)。exit()导致正常程序终止。我猜,这不是你想要的线程函数。只需使用
return
退出线程

4.-pthread_退出(0);在main()中。pthread_exit()函数终止调用线程。在main的末尾,您应该等待所有线程首先终止。使用
pthread\u join
(每个线程需要一个
pthread\u t
)。然后正常返回以退出程序


在进一步搜索之前,您应该先修复所有这些问题

不一定相关,但您可能希望查看您的文档。我看到您在等待之前立即解锁互斥锁,这是多余的。等待将为您解锁。类似地,从pthread_cond_wait返回时,互斥锁被锁定,这使得您在返回后立即重新锁定也是多余的。我建议你阅读你的pthreads书籍(或者我需要,因为它已经有一段时间了)。“我已经让程序运行得很好了,除了它在运行时停止的事实”-这听起来并不完美…现在我看了它,反正也没关系,因为我甚至没有看到pthread cond init创建那些条件变量,因此,这些等待无论如何都不会起作用。条件init位于程序的顶部。pthread_cond_t创建一个w
pthread_mutex_lock(&mutex);
while (!conditionMet) {
  //..
  pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);