2016-03-14 116 views
0

我目前正在開發一個多線程程序來代表一個有n個學生的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 */ 
    } 
    } 
} 

我的問題是我不能讓它正常工作。當我使用運行在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),我需要學生回家一次,連續不少次(如5)...

+0

什麼在你的代碼,你認爲停止同一個學生從一次又一次地坐下來? –

+0

什麼都沒有......我試着說sem_post(&studentSem)來釋放它,但沒有奏效! – cditomas

+0

請問什麼是「* TA *」?終端適配器? - ) – alk

回答

-1

此行在做什麼(學生){在void * student(void * param)中?

+0

這不提供答案。要申請更多信息,請發表評論。 – alk

+0

嗯。試過這樣做。因爲我沒有足夠的聲望,所以不讓我評論。 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)); 

附:

您可能需要使用不同的mutex爲TA,所以坐在椅子上可以pthread_mutex_lock(&TA_lock);,讓學生去到TA的時刻TA可...

...但是,這種方法的問題在於線路是未定義的(等待的學生沒有按照特定的順序選擇)......您可能想要爲座椅使用陣列/ bin-tree並讓TA處理隊列和學生用另一個循環,用互斥體保護bin-tree /數組。

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); 
    } 

    ....