【问题标题】:Multithreaded program exercise多线程程序练习
【发布时间】:2016-03-14 05:55:19
【问题描述】:

我目前正在开发一个多线程程序来代表一个有 n 个学生的 TA。当学生到达时,他们必须坐在走廊的椅子上(有 3 把椅子可用 + TA 办公室有 1 把椅子)。如果没有更多的椅子,他们必须回家等待。

这是我的代码:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include <semaphore.h>

pthread_mutex_t mutex; /* mutex lock */
sem_t studentSem;
sem_t taSem;

int chairs = 1;

void *student(void *param);
void *ta(void *param);

int main(int argc, char* argv[]){
  if(argc!=2){
    fprintf(stderr, "Un nombre d'etudiant est requis en paramètre\n");
    return -1;
  }

  if(atoi(argv[1])<0){
      fprintf(stderr, "Un nombre d'etudiant >= 0 est requis\n");
      return -1;
  }else{
    int numStudents = atoi(argv[1]);
    int numThreads = numStudents + 1; /* n etudiant + 1 TA */

    pthread_t tid[numThreads]; /* thread ID */
    pthread_attr_t attr; /* thread attributes */

    sem_init(&studentSem, 0, 1);
    sem_init(&taSem, 0, 0); /* 0 car TA attend etudiant */

    pthread_attr_init(&attr);

    int i = 0;
    pthread_create(&tid[i], &attr, ta, NULL); /*creer le TA*/

    for (i = 1; i < numThreads; i++){
      pthread_create(&tid[i], &attr, student, (void*)i); /*creer etudiant*/
    }

    for (i = 0; i < numThreads; i++){
      pthread_join(tid[i], NULL);
    }
  }
  return 0;

} /*fin du main*/

void *ta (void *param){ /*le thread pour TA*/
  while(ta){
    sem_post(&studentSem);
    pthread_mutex_lock(&mutex);
    chairs--;
    pthread_mutex_unlock(&mutex);
    printf("helping students\n");
    sleep(rand()%(1+3));
    sem_wait(&taSem);
  }
}

void *student(void *param){
  int *t;
  t = (int *)param;

  while(student){
    if(chairs < 4){
      pthread_mutex_lock(&mutex);         /* protects chairs */
      chairs++;                           /* incrementer chairs car etudiant prend cette chaise */
      pthread_mutex_unlock(&mutex);       /* releases mutex lock */
      printf("%i is sitting down\n", t);
      sem_post(&taSem);                   /* etudiant signal le TA pour demander de l'aide */
      sem_wait(&studentSem);              /* etudiant attend jusqua temps que TA l'aide et peut ensuite partir */
    } else {  /* no chairs available, so the student "goes home" */
      printf("%i is going home\n", t);
      sleep(rand()%(1+5)); /* sleeps a random amount of time */
    }
  }
}

我的问题是我无法让它正常工作。当我在 UNIX 上使用“sleepingTA 5”运行程序时,它给了我以下结果:

1 is sitting down
1 is sitting down
1 is sitting down
1 is sitting down
2 is sitting down
3 is going home
4 is going home
5 is going home
5 is going home 
1 is going home
1 is sitting down
...

循环总是无限工作。我不知道如何改变它,所以在得到帮助后,学生离开了......(不像回来的#1)。

另外,我需要学生只坐一次,而不是连续多次(比如 1 次),我需要学生回家一次,而不是连续多次(比如 5 次)...

【问题讨论】:

  • 您认为代码中的哪些内容可以阻止同一个学生一遍又一遍地坐下?
  • 什么都没有...我试着说 sem_post(&studentSem) 来释放它,但是没有用!
  • 请问什么是“TA”?终端适配器?-)

标签: c multithreading pthreads


【解决方案1】:

代码完全没有实现任何错误检查。如果它会测试相关库调用的结果,您会注意到(至少)所有pthread_mutex*() 调用都失败了,因为传入的互斥变量从未被初始化。

解决此问题的最简单方法是使用如下初始化程序:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

或者,代码可以在启动时初始化互斥锁:

#include <errno.h> /* for errno */

...

int main(int argc, char* argv[])
{
  if (0 != (errno = pthread_mutex_init(&mutex, NULL)))
  {
    perror("pthread_mutex_init() failed");
    exit(EXIT_FAILURE);
  }

  ....

【讨论】:

    【解决方案2】:

    不是完整的答案,而是...:

    在进入临界区之前,您正在检查椅子的数量。

    这意味着当您输入lock 时,chairs 中的数据可能不再有效。

      while(student){
        if(chairs < 4){
          pthread_mutex_lock(&mutex);         /* protects chairs */
          chairs++;                           /* incrementer chairs car etudiant prend cette chaise */
          pthread_mutex_unlock(&mutex);       /* releases mutex lock */
          printf("%i is sitting down\n", t);
          sem_post(&taSem);                   /* etudiant signal le TA pour demander de l'aide */
          sem_wait(&studentSem);              /* etudiant attend jusqua temps que TA l'aide et peut ensuite partir */
        } else {  /* no chairs available, so the student "goes home" */
          printf("%i is going home\n", t);
          sleep(rand()%(1+5)); /* sleeps a random amount of time */
        }
    

    我认为你需要在 if 语句之前输入锁。此外,您需要在完成后退出线程(或将student 设置为0)。

      while(student){
          pthread_mutex_lock(&mutex);         /* protects chairs */
        if(chairs < 4){
          chairs++;                           /* incrementer chairs car etudiant prend cette chaise */
          pthread_mutex_unlock(&mutex);       /* releases mutex lock */
          printf("%i is sitting down\n", t);
          sem_post(&taSem);                   /* etudiant signal le TA pour demander de l'aide */
          sem_wait(&studentSem);              /* etudiant attend jusqua temps que TA l'aide et peut ensuite partir */
          pthread_exit(0);              /* finish when you're done */
    
        } else {  /* no chairs available, so the student "goes home" */
          pthread_mutex_unlock(&mutex);       /* releases mutex lock */
          printf("%i is going home\n", t);
          sleep(rand()%(1+5)); /* sleeps a random amount of time */
        }
    

    另一件事是第一个i == 0...您可能希望使用i+1 来避免0 值作为学生标识符:

     pthread_create(&tid[i], &attr, student, (void*)(i+1));
    

    附言

    您可能想为助教使用不同的mutex,所以坐在椅子上的可能是pthread_mutex_lock(&amp;TA_lock);,所以学生在助教可用的那一刻就去助教...

    ...但是,这种方法的问题是该行未定义(未按特定顺序选择等待的学生)...您可能希望对椅子使用数组/bin-tree 和让 TA 处理队列,让学生使用另一个循环,用互斥锁保护 bin-tree/array。

    【讨论】:

      【解决方案3】:

      while(student){ in void *student(void *param) 中的这一行在做什么?

      【讨论】:

      • 这没有提供答案。要请求更多信息,请发表评论。
      • 嗯。试过这样做。不让我评论,因为我没有足够的声誉。顺便说一句,TA 是助教。
      猜你喜欢
      • 1970-01-01
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      相关资源
      最近更新 更多