Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 25.09.2017
Сообщений: 1

Работа с потоками

25.09.2017, 16:33. Показов 932. Ответов 1
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, уже третий день бьюсь над одной задачей:
Имеется группа из N студентов, в начале ленты они договариваются между собой в каком порядке будут защищать лабораторные работы преподавателю. Не сдавший студент идет в конец очереди. Каждый студент защищает лабораторную какое-то время, а также с какой-то вероятностью (равномерный закон распределения) положительного или отрицательного результата. Описанный процесс происходит бесконечно. Значение N также задается пользователем при старте процесса. В конце вывести список студентов, с пометкой «защитил»/«не защитил», сколько было попыток.

Как раз сейчас изучаются мьютексы и семафоры. По формулировке задания все можно было реализовать чисто под join-ы (ожидание завершения потока). Однако поговорив с преподавателем пришли к небольшой оговорке: студенты идут толпой, но сдают по одному. То есть у меня должны быть запущены ВСЕ потоки и уже если поток "студент" не сдаст, то он идет в конец списка, а далее идет следующий поток.

В связи с этим возникло несколько проблем:
1)Если не ждать завершения потока (join), то при запуске всех потоков они будут в разном порядке обращаться к функции, из-за чего потом невозможно точно простроить очередность запущенных потоков. При разных запусках - разные запущенные потоки.
2)Пробовал реализовать через рекурсивную функцию: поток запускает функцию, и если в ней получает значение "Не сдал", то в конце функции запускает еще один поток. При таком способе у меня запущенные в потоке функции уходили в конец списка, но при передаче значении они становились некорректными (например, номер студента при обычном запуске 1, а при запуске потока из потока: 2252542). Поэтому этот способ я тоже отбросил.
3)Решил пойти уже третьим способом и просто сделать бесконечный цикл, в котором он запускает потоки и если поток получает значение "Не сдал", то он при повторном прохождении цикла запускает еще раз поток с этими же значениями. Но и тут свои подводные камни: если цикл проходил и начинался заново, а в это время поток не успел изменить свое значение, то он запустит поток снова, из-за чего корректность значений опять падает. Из-за этого пришлось ставить таймеры, но с ними, получается, что я опять вернулся к самому первому варианту с join-ами, а мне надо чтобы ВСЕ потоки были запущены!!!

Помоги выйти из положения, скажите, возможно ли запускать несколько потоков и контролировать их очередность???

Вот моя последняя версия кода:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <pthread.h>
#include <semaphore.h>
 
 
sem_t Count_Of_Students; 
 
typedef struct SomedateOfStudent {
    int number;
    char character; 
    int repeat; 
    int times;  
} Student;
 
int ReadInt()
{
    int line = 0;
    while((line < 1) || (line > 10000)) 
    {
            scanf("%d", &line);
            while (getchar() != '\n');
                if ((line < 1) || (line > 10000))
                    printf("Введено некоректное значение, необходимо ввести число!\nПовторите ввод: ");
    }
    return line;
}
 
void* PassExam(void* args)
{
    sem_wait(&Count_Of_Students);
    srand (time(NULL));
    Student *arg = (Student*) args;
    int Time_Sleep;
    int SuccesOrRepeat;
    printf("Идет экзамен...\n\n");
        SuccesOrRepeat = rand () % 2;
    arg -> repeat++;
    sleep (arg -> times-1);
    printf("Номер студента: = %d\n", arg->number + 1);
    if (SuccesOrRepeat == 1)
    {
        printf("Успешно сдал!\n\n"); 
        arg -> character = 'R'; 
    }
    else
    { 
        printf("Не сдал :(\nНа пересдачу!\n\n");
        arg -> character = 'F';
    }
    sem_post(&Count_Of_Students);
}
 
int main()
{
     sem_init(&Count_Of_Students, 0, 1);
     int CountOfStudent;
     int PassedStudents; 
     int Time_Sleep;
     int j;
     printf("Добро пожаловать на сдачу экзамена!\nВведите количество студентов:\n\n");
     CountOfStudent = ReadInt();
         Student args[CountOfStudent];
     system("clear");
     printf("Начинается экзамен!\n\n");
     sleep(2);  
     for (int i = 0; i < CountOfStudent; i++) 
     {
        printf("Ждем следующего студента...\n\n");
        sleep (2 + rand() % 5);
        Time_Sleep = 2 + rand() % 6;
        args[i].times = Time_Sleep;
            args[i].number = i;
        args[i].repeat = 0;
        pthread_t student;
            pthread_create(&student, NULL, &PassExam, (void*) &args[i]);
        sleep (Time_Sleep);
        }
    sleep(2);
    j = 1;
    system("clear");
    printf("Начинаются пересдачи!\n\n");
        sleep(3);   
    for (int k = 0; k < 3; k++)
    {
        PassedStudents = CountOfStudent;
        for (int i = 0; i < CountOfStudent; i++) 
        {
            if (args[i].character == 'R')
                PassedStudents = PassedStudents-1;
        }
        if (PassedStudents == 0)
                break;
        system("clear");
        printf("Начинается %d пересдача...\n\n", j);
        for (int i = 0; i < CountOfStudent; i++) 
        {
            Time_Sleep = 2 + rand() % 6;
            args[i].times = Time_Sleep;
            if (args[i].character == 'F')
            {
                printf("Ждем следующего студента...\n\n");
                sleep (2 + rand() % 5);
                pthread_t student;
                    pthread_create(&student, NULL, &PassExam, (void*) &args[i]);
                sleep (Time_Sleep);
            }
        }
        j++;
    }
    sleep(3);
    system("clear");
    printf("Результаты экзаменов!\n");
    for (int i = 0; i < CountOfStudent; i++) 
    {
         printf("\nCтудент под номером %d:\n", args[i].number+1);
         if (args[i].character == 'R') 
             printf("Сдал с %d попытки.\n\n", args[i].repeat);
         else 
             printf("Не сдал экзамен.\n\n");
    }
    sem_destroy(&Count_Of_Students);
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.09.2017, 16:33
Ответы с готовыми решениями:

Работа с потоками
Здесь на форуме нашел темку, где была представлена проблема с которой столкнулся я сам, но её никто не решил. Вот она: &quot;Добрый...

Обработка файлов потоками
Здравствуйте, столкнулась вот с какой проблемой. Пользователь с клавиатуры вводит количество потоков. Я не понимаю, как сделать так, чтобы,...

Переделать задачу с потоками на fork
Нужно скопировать файл, использую параллельное программирование. Есть реализация этой задачи с использованием потоков(pthread), нужно...

1
1267 / 980 / 385
Регистрация: 02.09.2012
Сообщений: 3,027
25.09.2017, 22:49
Напрашивается схема, когда главный поток (который выполняет main) является преподавателем, который может контролировать через дополнительный мьютекс попадание студента на экзамен. Он же, преподаватель, может давать результат вероятностной функции результата сдачи. Вам нужно сначала создать группу студентов в отдельном цикле, потом в другом цикле "провести экзамен" до тех пор, пока все студенты не сдадут. Третий цикл "пересдач" уже будет не нужен.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.09.2017, 22:49
Помогаю со студенческими работами здесь

TCP/IP сервер - клиент - как работать с потоками?
Доброго времени суток, друзья. Пытаюсь создать локальный чат по типу клиент-сервер по протоколу tcp/ip. Имеется большая проблема с...

Один элемент в списке обрабатывается двумя потоками
Суть такова: есть 2 потока, первый обходит двусвязный список с головы и считает нулевые биты в значениях элементов. Второй поток должен...

Передача файла между потоками поблочно с помощью пайпов
Можно ли от одного потока передавать файл к другому через pipe поблочно? Если да то как?!

Базовые операции с параллельными потоками операционной системы Linux
Доброе время суток, могли бы помочь в таком задании, и рассказать что как и как:

Базовые операции с параллельными потоками операционной системы Linux 2
Еще один вариант реализации параллельных потоков:


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru