线程中的沉睡教授问题使用C语言同步
该代码由于某种原因不起作用
课程结束后,教授喜欢睡觉 - 除了学生 困扰他们回答问题。你必须写下程序 同步代表一位教授和任意的线程 学生人数。一位无关紧要的教授,请致电idleprof(), 哪个检查学生是否在办公室外面等待 一个问题。如果没有学生在等待,就会睡觉; 否则,它标志着一个学生进入办公室并返回。一个 有一个问题要问电话到达()的学生, 学生队列在办公室外等待信号 教授;如果没有学生在等待,那么学生就醒来了 睡觉的教授。这个想法是教授和 一个学生将从各自的职能中返回 时间”:返回后,他们讨论了一个相互兴趣的话题,然后 学生可以回到学习,教授打电话给idleprof 再次。使用Mutexes和 条件变量。您可能假设静音和状况 变量是公平的(例如,fifo)。
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include <stdbool.h>
pthread_mutex_t mutex; pthread_cond_t prof,stud; int busy = 1; int std_nb = 0;
void *IdleProf() {
//prof sleeping
busy = 0;
while(1){
if(std_nb == 0) {
printf("Professor is sleeping");
pthread_cond_wait(&stud, &mutex);
}
else {
pthread_mutex_lock(&mutex);
busy = 1;
printf("Professor is busy ");
std_nb--;
pthread_cond_signal(&prof);
pthread_mutex_unlock(&mutex);
}
} }
void *ArrivingStudents() {
pthread_mutex_lock(&mutex);
if(busy == 0 && std_nb == 0) {
busy = 1;
// Waking up the Prof
pthread_cond_signal(&stud);
printf("Professor woke up ");
pthread_mutex_unlock(&mutex);
}
else {
std_nb++;
//wait for students
pthread_cond_wait(&prof,&mutex);
pthread_mutex_unlock(&mutex);
}
}
int main() {
printf("Students Number?: ");
scanf("%d",std_nb);
pthread_t *thread;
thread = (pthread_t*)malloc(sizeof(pthread_t)*std_nb);
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&prof,NULL);
pthread_cond_init(&stud,NULL);
for(int i=0;i<std_nb;i++) {
pthread_create(&thread[i],NULL,IdleProf,NULL);
}
for(int i=0;i<std_nb;i++) {
pthread_create(&thread[i],NULL,ArrivingStudents,NULL);
}
for(int i=0;i<std_nb;i++) {
pthread_join(thread[i],NULL);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&prof);
pthread_cond_destroy(&stud);
pthread_exit(NULL); }
the code isn't working for some reason
Once class is over, professors like to sleep — except when students
bother them to answer questions. You have to write procedures to
synchronize threads representing one professor and an arbitrary
number of students. A professor with nothing to do calls IdleProf(),
which checks to see if a student is waiting outside the office to ask
a question. IdleProf sleeps if there are no students waiting;
otherwise, it signals one student to enter the office, and returns. A
student with a question to ask calls ArrivingStudent(), which joins
the queue of students waiting outside the office for a signal from
the professor; if no students are waiting, then the student wakes up
the sleeping professor. The idea is that the professor and exactly
one student will return from their respective functions “at the same
time”: after returning they discuss a topic of mutual interest, then
the student goes back to studying and the professor calls IdleProf
again. Implement IdleProf and ArrivingStudent using mutexes and
condition variables. You may assume that mutexes and condition
variables are fair (e.g., FIFO).
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include <stdbool.h>
pthread_mutex_t mutex; pthread_cond_t prof,stud; int busy = 1; int std_nb = 0;
void *IdleProf() {
//prof sleeping
busy = 0;
while(1){
if(std_nb == 0) {
printf("Professor is sleeping");
pthread_cond_wait(&stud, &mutex);
}
else {
pthread_mutex_lock(&mutex);
busy = 1;
printf("Professor is busy ");
std_nb--;
pthread_cond_signal(&prof);
pthread_mutex_unlock(&mutex);
}
} }
void *ArrivingStudents() {
pthread_mutex_lock(&mutex);
if(busy == 0 && std_nb == 0) {
busy = 1;
// Waking up the Prof
pthread_cond_signal(&stud);
printf("Professor woke up ");
pthread_mutex_unlock(&mutex);
}
else {
std_nb++;
//wait for students
pthread_cond_wait(&prof,&mutex);
pthread_mutex_unlock(&mutex);
}
}
int main() {
printf("Students Number?: ");
scanf("%d",std_nb);
pthread_t *thread;
thread = (pthread_t*)malloc(sizeof(pthread_t)*std_nb);
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&prof,NULL);
pthread_cond_init(&stud,NULL);
for(int i=0;i<std_nb;i++) {
pthread_create(&thread[i],NULL,IdleProf,NULL);
}
for(int i=0;i<std_nb;i++) {
pthread_create(&thread[i],NULL,ArrivingStudents,NULL);
}
for(int i=0;i<std_nb;i++) {
pthread_join(thread[i],NULL);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&prof);
pthread_cond_destroy(&stud);
pthread_exit(NULL); }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要考虑两个条件的条件。
教授必须睡觉,直到学生队列超过0。
当学生队列等于0时,教授必须恢复睡觉,并且教授不与学生讨论(可用)。
每个学生都必须等待队列,直到该学生处于队列并有教授。
为了使问题更有趣,教授和学生之间的每次会议都可能需要不同的时间。
以下是使用ADA编程语言编写的解决方案。
该解决方案使用ADA受保护的对象,该对象实现了Hoare监视器。 受保护的对象描述
在两个部分中实现了一个受保护的对象。受保护的对象规范既定义了受保护对象的API,也定义了受保护对象的任何私人数据成员。受保护的身体实现了定义为受保护对象的API的操作。
名为Student_queue的受保护对象实现了两个受保护的条目和一个受保护的程序。在学生_Queue的主体中,我们看到条目IDLE_PROF包含条件 arriving_student'count&gt; 0 。由于受保护的条目可以阻止呼叫任务,因此将阻止的任务隐式放置在条目队列中。此表达式简单地评估与条目arrive_student关联的条目队列中等待的任务数。 IDLE_PROF的目的是暂停教授,直到学生进入队列为止。
条目arriving_student具有prof_available的条件,每当教授不与学生参加会议时,这是正确的。
受保护的过程toggle_prof_available提供了一个API,因此与教授会议中的学生任务可以将Student_queue的Prof_available数据成员设置为与教授一起度过随机时间后的true。
为教授宣告了一项ADA任务,并为学生宣布ADA任务类型。任务类型允许创建任意数量的学生任务实例。
ADA任务可以具有条目,允许任务直接与其他任务同步通信。教授任务有两个名为Start和完成的条目。开始入口使教授暂停,直到该计划准备在教授和任意数量的学生任务之间实施会议为止。完成的条目用于向教授任务发出终止的信号。
学生任务类型主体实现了学生的行为。学生任务主体中的接受声明会导致任务实例暂停,直到调用其se_professor条目,然后将学生编号传递给学生任务。然后,学生实例致电student_queue.Arriving_student,传递其ID号。该任务将暂停在Arriving_student入口队列中,直到该任务实例处于队列和教授的负责人。执行Arriving_student受保护条目后,学生实例延迟(类似于C睡眠)在0.0到1.0秒之间随机时间。延迟到期后,学生任务调用toggle_prof_available可使教授可用于另一个学生实例。最后,学生任务实例终止。
教授任务在上等待接受start 语句,以便等待主要任务致电教授。然后,教授任务进入一个无限的循环,该循环仅在主要任务称为教授时才终止。每次通过循环,教授任务都有条件地接受完成的条目,如果尚未调用,教授任务称为student_queue.idle_prof。如果没有立即处理该输入电话,则教授任务输出字符串“睡眠教授”。并重复其内部循环迭代。
主线程声明了一个名为Student_list的不受约束的数组类型,该类型是一系列学生任务。它还声明了一个可变num_students,该变量将容纳大于0的整数,该整数将由用户输入。
提示用户的学生人数,并将用户输入分配给NUM_STUDENTS。
定义了内部块。在该块的“声明性”部分中,创建了一个名为“学生”的实例,该实例由用户输入指定的元素数量创建。
教授开始被称为,导致教授开始与等待的学生开始睡觉和/或会议。通过学生数组来调用See_professor的循环,将学生ID设置为该数组中该元素的索引。要求延迟0.001秒,以确保操作系统调度允许按预期顺序处理学生任务。
内部块的使用具有pthreads的效果,加入了所有学生任务。在所有学生线程完成之前,内部块将无法完成。
最后,主要任务称为教授。
该程序的示例执行是:
The conditions you need to consider two conditions.
The professor must sleep until the queue of students exceeds 0.
The professor must resume sleeping when the queue of students equals 0 and the professor is not in discussion with a student (is available).
Each student must wait in the queue until that student is at the head of the queue and the professor is available.
To make the problem more interesting, each conference between the professor and a student can take a different amount of time.
Following is a solution written using the Ada programming language.
This solution uses an Ada protected object, which implements a Hoare Monitor. Protected object description
A protected object is implemented in two parts. The protected object specification defines both the API for the protected object and any private data members of the protected object. The protected body implements the operations defined as the API of the protected object.
The protected object named student_queue implements two protected entries and one protected procedure. In the body for student_queue we see that the entry Idle_Prof contains the condition Arriving_Student'Count > 0. Since protected entries can block a calling task the blocked tasks are implicitly placed in an entry queue. This expression simply evaluates the number of tasks waiting in the entry queue associated with the entry Arriving_Student. The purpose of Idle_Prof is to suspend Professor until a student enters the queue.
The entry Arriving_Student has a condition Prof_Available which is true whenever the professor is not in conference with a student.
The protected procedure Toggle_Prof_Available provides an API so that the Student task in conference with the Professor can set the Prof_Available data member of student_queue to TRUE after spending a random time with the Professor.
One Ada task is declared for the Professor and an Ada task type is declared for the student. The task type allows an arbitrary number of instances of a student task to be created.
Ada tasks can have entries, allowing tasks to synchronously communicate directly with other tasks. The Professor task has two entries named Start and Done. The Start entry causes the Professor to suspend until the program is ready to implement conferences between the Professor and an arbitrary number of Student tasks. The Done entry is used to signal the Professor task to terminate.
The Student task type body implements the behavior of the student. The accept statement in the Student task body causes the task instance to suspend until its See_Professor entry is called, passing a student number to the student task. The Student instance then calls student_queue.Arriving_Student, passing its ID number. The task will suspend in the Arriving_Student entry queue until that task instance is at the head of the queue and Professor is available. After executing the Arriving_Student protected entry the Student instance delays (similar to a C sleep) for a random time between 0.0 and 1.0 seconds. After the delay expires the Student task calls Toggle_Prof_Available to make the Professor available to another Student instance. Finally, the Student task instance terminates.
The Professor task waits at the Accept Start statement so that it will wait until the main task calls Professor.Start. The Professor task then enters an infinite loop that is only terminated when the main task calls Professor.Done. Each time through the loop the Professor task conditionally accepts the Done entry, and if it has not yet been called, the Professor task calls Student_Queue.Idle_Prof. If that entry call is not immediately handled the Professor task output the string "Professor sleeping." and repeats its internal loop iteration.
The main thread declares an unconstrained array type named Student_List which is an array of Student tasks. It also declares a variable Num_Students which will hold an integer greater than 0 which will be entered by the user.
The user is prompted for the number of students and the user input is assigned to Num_Students.
An internal block is defined. In the declarative section of the block an instance of Student_List named Students is created with the number of elements specified by the user input.
Professor.Start is called, causing the Professor to start sleeping and/or conferencing with waiting students. A loop incrementing through the Students array calls See_Professor, setting the Student ID to the index of that element in the array. A delay of 0.001 seconds is called to ensure that Operating System scheduling allows the Student tasks to be handled in the expected order.
The use of the internal block has the effect of a pthreads join call on all the Student tasks. The internal block will not complete until all the Student threads are complete.
Finally the main task calls Professor.Done and the program terminates.
A sample execution of the program is: