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

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

18.12.2018, 15:33. Показов 841. Ответов 2

Студворк — интернет-сервис помощи студентам
Здесь на форуме нашел темку, где была представлена проблема с которой столкнулся я сам, но её никто не решил. Вот она:

"Добрый день, уже третий день бьюсь над одной задачей:
Имеется группа из 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,i,k;
     printf("Добро пожаловать на сдачу экзамена!\nВведите количество студентов:\n\n");
     CountOfStudent = ReadInt();
         Student args[CountOfStudent];
     system("clear");
     printf("Начинается экзамен!\n\n");
     sleep(2);  
     for (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 (k = 0; k < 3; k++)
    {
        PassedStudents = CountOfStudent;
        for (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 (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 (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;
}
К ней был приложен ответ: "Напрашивается схема, когда главный поток (который выполняет main) является преподавателем, который может контролировать через дополнительный мьютекс попадание студента на экзамен. Он же, преподаватель, может давать результат вероятностной функции результата сдачи. Вам нужно сначала создать группу студентов в отдельном цикле, потом в другом цикле "провести экзамен" до тех пор, пока все студенты не сдадут. Третий цикл "пересдач" уже будет не нужен."

Но этого мало, хотелось бы увидеть решение в виде кода.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
18.12.2018, 15:33
Ответы с готовыми решениями:

Работа с потоками
Добрый день, уже третий день бьюсь над одной задачей: Имеется группа из N студентов, в начале ленты они договариваются между собой...

Работа с потоками на VB.
Собственно субж, ... немог бы кто дать какие нибуди примерчики.

Работа с потоками
Здравствуйте! Такой вопрос. Как на выполнение какой либо операции, например на чтение файла веслом 24 гб, выделить 1,2 или 3 потока, и...

2
112 / 91 / 31
Регистрация: 24.10.2018
Сообщений: 336
18.12.2018, 15:48
Зачем здесь нужны потоки, если в один момент времени только один студент сдает лабораторную? Почему это не просто очередь студентов? Берем одного, и дальше он либо уходит, либо снова становится в очередь.
0
0 / 0 / 0
Регистрация: 18.12.2018
Сообщений: 7
18.12.2018, 15:57  [ТС]
потому что стоит задача, решить с помощью потоков, каждый студент это один поток, а с помощью семафоров и мьютексов реализовать очередь выполнения
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.12.2018, 15:57
Помогаю со студенческими работами здесь

Работа с потоками
r113_object = new r113_Object(0); thread = new QThread(0); r113_object-&gt;moveToThread(thread); В классе зациклена функция и наверно...

Работа с потоками
Здравствуйте. нужно доработать программу чтобы я вводил количество потоков. предположим что это программа Поставщик-Потребитель...с...

Работа с потоками
Переделал код под работу в потоках, но при запуске на андроиде черный экран, помогите поправить. unit Unit1; interface uses ...

Работа с потоками
Задание Разработать программу, реализующую многопочность средствами среды Win32. Программа должна обеспечивать: Отображение списка...

Работа с потоками
Нужно сделать программу которая скачивает несколько файлов в разных потоках.


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

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
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
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru