我目前正在开发一个多线程程序来表示一个有n个学生的助教。当学生到达时,他们必须坐在走廊的椅子上(助教办公室有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谁回来了)。
此外,我需要学生只坐一次,而不是连续坐很多次(比如1次),我需要学生回家一次,而不是连续多次(比如5次)……
发布于 2016-03-14 14:58:28
代码完全缺失,无法实现任何错误检查。如果它测试相关库调用的结果,您会注意到(至少)所有的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);
}
....发布于 2016-03-14 14:26:33
不是全部的答案,但是……
在进入临界区之前,您要检查椅子的数量。
这意味着当您输入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(&TA_lock);,因此学生在助教可用时就去找助教……
...but,这种方法的问题是排队是不确定的(等待的学生不是按特定顺序选择的)……您可能希望对椅子使用数组/bin-tree,并让助教使用另一个循环来处理队列和学生,从而使用互斥保护bin-tree/array。
发布于 2016-03-14 14:06:47
当(Student){ in void *student(void *param)时,这行在做什么?
https://stackoverflow.com/questions/35980422
复制相似问题