2016-03-14 2 views
0

В настоящее время я работаю над многопоточной программой для представления TA с русскими учениками. Когда студенты приходят, они должны сидеть в коридоре на стуле (в офисе TA есть 3 стула + 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 */ 
    } 
    } 
} 

Моя проблема в том, что я не могу заставить его работать правильно. Когда я запускаю программу с помощью «sleepingTA 5» на UNIX, это дает мне следующий результат:

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) ...

+0

Что в вашем коде вы думаете, останавливает тот же студент, сидящий снова и снова? –

+0

Ничего еще ... Я попробовал сказать sem_post (& studentSem), чтобы выпустить его, но не сработал! – cditomas

+0

Пожалуйста, что такое «* TA *»? Терминальный адаптер? -) – alk

ответ

-1

Что это за линия в то время как (студент) {in void * student (void * param)?

+0

Это не дает ответа. Чтобы запросить дополнительную информацию, оставьте комментарий. – alk

+0

Ummm. Пробовал это делать. Не позволяет мне прокомментировать, так как у меня недостаточно репутации. Btw, TA - помощник преподавателя. –

0

не весь ответ, но ...:

Вы выполняете проверку на количество стульев перед входом в критическую секцию.

Это означает, что к моменту ввода 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)); 

P.S.

Вы можете использовать другой mutex для ТОГО, так сидит в кресле может быть pthread_mutex_lock(&TA_lock);, поэтому студенты идут на ТОТ момент ТОЙ доступен ...

... но, проблема с этим подходом заключается в том, что строка не определена (ожидающие студенты не выбраны в определенном порядке) ... вы можете использовать массив/бин-дерево для стульев и иметь ТА, обрабатывающие очередь, и студенты с другим циклом, защищая бин-дерево/массив с помощью мьютекса.

1

Код полностью пропускает выполнение любой проверки ошибок. Если бы он тестировал результаты соответствующих вызовов библиотеки, вы бы заметили, что (по крайней мере) все вызовы pthread_mutex*() терпят неудачу, потому что переданная переменная 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); 
    } 

    .... 
Смежные вопросы