Вопрос или проблема
Я хочу, чтобы каждый раз, когда создается студент, отображалось, кто был создан и в каком department они учатся. Я застрял и не знаю, какие параметры передать в printInfo(), есть у вас идеи? Я также предоставляю пример выполнения
Вывод:
Введите количество студентов:
5
Студент 1 (Математика) создан.
Остановка A: [1, Математика]
Автобус:
Университет:
Остановка B:
Студент 2 (Химия) создан.
Остановка A: [1, Математика] [2, Химия]
Автобус:
Университет:
Остановка B:
....
Студент 4 (Математика) создан.
Остановка A: [1, Математика] [2, Химия] [3, Физика] [5, Физика] [4, Математика]
Автобус:
Университет:
Остановка B:
и самая большая часть моего кода:
...
sem_t semaphore;
pthread_barrier_t barrier;
pthread_mutex_t mutex;
int count=0;
enum place{
stopA=0,
Bus=1,
University=2,
stopB=3
};
enum science{
Math=0,
Physics=1,
Chemistry=2,
CSD=3
};
struct student{
pthread_t thread;
int am;
int time;
enum place position;
enum science department;
};
...
void initialize_students(struct student * Student, pthread_t thread, int i){
Student->thread=thread;
Student->am=random_number(1000,6000);
Student->time=random_number(5,15);
Student->position=stopA;
Student->department=random_number(0,3);
return;
}
void printInfo(struct student * s,int num){
printf("\nОстановка A: ");
for(int i=0;i<num;i++){
if(s->position==stopA){
printf("[%d , %s ] ",i,getScience(s[i].department));
}
}
printf("\nАвтобус: ");
for(int i=0;i<num;i++){
if(s->position==Bus){
printf("[%d , %s ] ",i,getScience((s+i)->department));
}
}
printf("\nУниверситет: ");
for(int i=0;i<num;i++){
if(s->position==University){
printf("[%d , %s ] ",i,getScience((s+i)->department));
}
}
printf("\nОстановка B: ");
for(int i=0;i<num;i++){
if(s->position==stopB){
printf("[%d , %s ] ",i,getScience((s+i)->department));
}
}
printf("\n");
}
void * startEvent(void * args){
struct student * s = (struct student*)args;
pthread_mutex_lock(&mutex);
printf("\nСтудент %d [%s] создан\n",++count,getScience(s->department));
sleep(1);
printInfo();
pthread_mutex_unlock(&mutex);
}
int main(){
int NUM_THREADS;
int i;
printf("Пожалуйста, введите количество студентов:\n");
scanf("%d", &NUM_THREADS);
if (NUM_THREADS < 12 || NUM_THREADS > 200) {
perror("Неверное количество студентов. Оно должно быть между 12 и 200.\n");
return EXIT_FAILURE;
}
pthread_t * thread=malloc(NUM_THREADS * sizeof(pthread_t));
srand(time(NULL));
struct student * Students=malloc(NUM_THREADS * sizeof(struct student));
for(i=0;i<NUM_THREADS;i++){
initialize_students((Students+i),thread[i],i);
}
sem_init(&semaphore,0,NUM_THREADS);
pthread_mutex_init(&mutex,NULL);
for(i=0;i<NUM_THREADS;i++){
if( pthread_create(&Students[i].thread,NULL,&startEvent,&Students[i]) != 0 ){
perror("Ошибка при попытке создать поток\n");
}
}
for(i=0;i<NUM_THREADS;i++){
if( pthread_join(Students[i].thread,NULL) != 0 ){
perror("Ошибка при соединении потока\n");
}
}
return 0;
}
place: Представляет места, где можно найти студента (остановки A, B, автобус, университет).
science: Представляет предмет изучения студента (Математика, Физика, Химия, CSD).
thread: идентификатор потока.
am: случайное число, представляющее AM (Регистрационный номер).
time: длительность пребывания в университете.
position: текущее местоположение студента.
department: его факультет.
random_number генерирует случайное целое число в заданном диапазоне (от min до max)
Ответ или решение
Понимание потоков и семафоров (POSIX семафоры) является важной частью разработки многопоточных приложений, особенно когда необходимо координировать взаимодействие между потоками. Ваша задача состоит в том, чтобы правильно передать параметры в функцию printInfo()
, чтобы она могла отобразить информацию о созданных студентах.
Параметры для передачи в printInfo()
Ваша функция printInfo()
требует два параметра:
- Указатель на массив студентов (
struct student *s
) - Общее количество студентов (
int num
)
Таким образом, код вызова printInfo()
в функции startEvent()
должен быть модифицирован следующим образом:
printInfo(Students, NUM_THREADS);
Это обеспечит корректное отображение информации о всех студентах. Параметр Students
указывает на массив структур студентов, а NUM_THREADS
позволяет функции printInfo()
определить количество созданных студентов.
Обзор кода
Ваш код создает потоки для каждого студента, используя POSIX потоки и семафоры для обеспечения правильной синхронизации. Рассмотрим основные части вашего кода подробнее:
-
Структура студента (
struct student
) содержит информацию о каждом студенте, включая идентификатор потока, случайный регистрационный номер, время, позицию и отделение. -
Функция
initialize_students()
инициализирует нового студента, присваивая ему уникальные значения для каждого параметра. -
Синхронизация с использованием
pthread_mutex_t
позволяет избежать конфликтов при выводе информации о студентах. Каждое создание студента и вывод информации фиксируется с помощью блокировки и разблокировки мьютекса. -
Вывод информации: Функция
printInfo()
выделяет место для каждого студента в различных категориях (остановки, автобус, университет), используя условиеif
для определения текущей позиции.
Рекомендации по улучшению кода
-
Инкапсуляция логики вывода: Возможно, будет гуманно разделить логику, связанную с выводом конкурентных состояний (
printInfo()
), и выделить её в отдельные функции. Это повысит читаемость кода и упростит изменения в будущем. -
Управление памятью: Обязательно не забывайте освобождать выделенную память для
Students
иthread
, чтобы избежать утечек памяти. В конце функцииmain()
добавьте:
free(Students);
free(thread);
- Обработка ошибок: При работе с потоками важно обрабатывать возможные ошибки, связанные с созданием или объединением потоков. Хотя у вас уже есть это в коде, вы можете добавить больше информации в сообщения об ошибках, чтобы упростить отладку.
Заключение
Использование потоков и семафоров в C может быть сложной задачей, особенно при необходимости управлять состоянием нескольких потоков. В вашем случае, правильный вызов функции printInfo()
и корректная работа с потоками позволяют добиться требуемого поведения вашего приложения. Следуя данным рекомендациям, вы сможете улучшить ваш код и сделать его более устойчивым и понятным. Если у вас возникли дополнительные вопросы, не стесняйтесь спрашивать.