Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/37: Рейтинг темы: голосов - 37, средняя оценка - 4.57
 Аватар для sergeyotro
0 / 0 / 0
Регистрация: 08.10.2011
Сообщений: 13

Задача "Производители-Потребители", реализация с помощью Events и циклического буфера

23.10.2011, 14:41. Показов 7561. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток.

Написал программу для решения сабжевой задачи, с условиями 1 производитель, 1 потребитель.
Программа работает, потоки синхронизируются, тупиков не возникает.

Однако, условия поменялись и нужно изменить текст программы таким образом, что бы производителей было несколько, а потребитель один. Попытался реализовать такие условия, но не могу уместить в голове синхронизацию не только между производителем-потребителем, но и между производителями, что бы они делили буфер и не пытались туда писать одновременно.

В реализации этого условия и прошу помочь. Улучшения кода по первому условию так же приветствуется.

Ниже - текст программы с 1 производителем и 1 потребителем.
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
#include <iostream>
#include <conio.h>
#include <windows.h>
 
using namespace std;
 
unsigned long uThrProdID1, uThrConsID;
 
HANDLE hEventWrite, hEventRead;
HANDLE hThrProd1, hThrCons;
void ProducerThread(char name[11]);
void ConsumerThread(void *pParams);
 
#define SIZE_BUF 25
 
int cycleBuf[SIZE_BUF];
int tail = 0;
int head = 0;
int count = 0;
 
void FlushBuf(void);
void PutChar(int sym);
int GetChar(void);
 
int main()
{
    FlushBuf();
 
    hEventWrite = CreateEvent(NULL, FALSE, FALSE, NULL);
    hEventRead = CreateEvent(NULL, FALSE, TRUE, NULL);
 
    hThrProd1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProducerThread, "Producer 1", 0, &uThrProdID1);
 
    hThrCons = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ConsumerThread, NULL, 0, &uThrConsID);
 
    getch();
    return 0;
}
 
void ProducerThread(char name[11])
{
    WaitForSingleObject(hEventRead, INFINITE);
    while(1)
    {
        Sleep(rand()%500);
 
        while (count < SIZE_BUF)
            PutChar(rand());
 
        cout <<  name << ": There are " << count << " symbols in buf" << endl << endl;
        SetEvent(hEventWrite);
    }
}
 
void ConsumerThread(void *pParams)
{
    WaitForSingleObject(hEventWrite, INFINITE);
    while(1)
    {
        Sleep(rand()%50);
 
        if (count == 0)
        {
            SetEvent(hEventRead);
            WaitForSingleObject(hEventWrite, INFINITE);
        }
 
        GetChar();
        cout << "Consumer: There are " << count << " symbols in buf now." << endl << endl;
    }
}
 
void FlushBuf(void)
{
    tail = 0;
    head = 0;
    count = 0;
}
 
void PutChar(int sym)
{
    if (count < SIZE_BUF)
    {
        cycleBuf[tail] = sym;
        count++;
        tail++;
        if (tail == SIZE_BUF) tail = 0;
    }
}
 
int GetChar(void)
{
    int sym = 0;
    if (count > 0)
    {
        sym = cycleBuf[head];
        count--;
        head++;
        if (head == SIZE_BUF) head = 0;
    }
    return sym;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.10.2011, 14:41
Ответы с готовыми решениями:

Задача производители потребители
Задача производители-потребители Должна быть решена проблема работы нескольких процессов с одним буфером. Часть процессов это...

Задача "Производители-Потребители", Win ip
Здравствуйте, нужна ваша помощь! Необходимо разработать задачу &quot;Производители-Потребители&quot; по данному изображению. Может у кого-то...

Производители и потребители
Доброго времени суток. Стоит задача производителей и потребителей на основе механизма обмена сообщениями. Буфер сообщений должен быть...

4
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.10.2011, 20:08
Цитата Сообщение от sergeyotro Посмотреть сообщение
не могу уместить в голове синхронизацию не только между производителем-потребителем, но и между производителями
использую блокируемую очередь.
1
 Аватар для sergeyotro
0 / 0 / 0
Регистрация: 08.10.2011
Сообщений: 13
23.10.2011, 22:28  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
использую блокируемую очередь.
Спасибо за подсказку. Надеюсь я её правильно понял.

Вот код изменённой программы, работает правильно. Надеюсь, кому-нибудь пригодится.
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <conio.h>
#include <windows.h>
#define MAX_PRODUCERS 6
#define SIZE_BUF 25
//#define READ_OUTPUT
 
using namespace std;
 
DWORD uThrProdID[MAX_PRODUCERS], uThrConsID;
 
HANDLE hEventWrite, hEventRead, hEventBuf;
HANDLE hThrProdArray[MAX_PRODUCERS], hThrCons;
 
void ProducerThread(char name[11]);
void ConsumerThread(void *pParams);
 
int cycleBuf[SIZE_BUF];
int tail = 0;
int head = 0;
int count = 0;
 
void FlushBuf(void);
void PutChar(int sym);
int GetChar(void);
 
FILE *fw;
 
#ifdef READ_OUTPUT
FILE *fr;
#endif
 
int main()
{
    fw = fopen("bufw.txt", "w");
#ifdef READ_OUTPUT
    fr = fopen("bufr.txt", "w");
#endif
    FlushBuf();
 
    hEventWrite = CreateEvent(NULL, FALSE, FALSE, NULL);
    hEventBuf = CreateEvent(NULL, FALSE, TRUE, NULL);
    hEventRead = CreateEvent(NULL, FALSE, TRUE, NULL);
 
    for ( int i = 0; i < MAX_PRODUCERS; i++ )
    {
        char* prod = new char[11];
        sprintf(prod, "Producer %d", i+1);
        hThrProdArray[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProducerThread, prod, 0, &uThrProdID[i]);
    }
 
    hThrCons = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ConsumerThread, NULL, 0, &uThrConsID);
 
    getch();
 
    fclose(fw);
#ifdef READ_OUTPUT
    fclose(fr);
#endif
 
    CloseHandle(hEventBuf);
    CloseHandle(hEventRead);
    CloseHandle(hEventWrite);
 
    for ( int i = 0; i < MAX_PRODUCERS; i++ )
        CloseHandle(hThrProdArray[i]);
 
    CloseHandle(hThrCons);
    return 0;
}
 
void ProducerThread(char name[11])
{
    while(1)
    {
        WaitForSingleObject(hEventRead, INFINITE);
        Sleep(rand()%500);
        if (count < SIZE_BUF)
        {
            for ( int i = 0; i < 3; i++ )
            {
                PutChar(name[9]);
                putc(name[9], fw);
            }
            putc(13, fw);
        }
        cout <<  name << ": There are " << count << " symbols in buf" << endl << endl;
        SetEvent(hEventWrite);
    }
}
 
void ConsumerThread(void *pParams)
{
    WaitForSingleObject(hEventWrite, INFINITE);
    while(1)
    {
        Sleep(rand()%50);
        if (count == 0)
        {
            SetEvent(hEventRead);
            WaitForSingleObject(hEventWrite, INFINITE);
        }
#ifdef READ_OUTPUT
        putc(GetChar(), fr);
#else
        GetChar();
#endif
        cout << "Consumer: I've read one symbol. There are " << count << " symbols in buf now. " << endl << endl;
        SetEvent(hEventRead);
    }
}
 
void FlushBuf(void)
{
    tail = 0;
    head = 0;
    count = 0;
}
 
void PutChar(int sym)
{
    WaitForSingleObject(hEventBuf, INFINITE);
    if (count < SIZE_BUF)
    {
        cycleBuf[tail] = sym;
        count++;
        tail++;
        if (tail == SIZE_BUF) tail = 0;
    }
    SetEvent(hEventBuf);
}
 
int GetChar(void)
{
    int sym = 0;
    if (count > 0)
    {
        sym = cycleBuf[head];
        count--;
        head++;
        if (head == SIZE_BUF) head = 0;
    }
    return sym;
}
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.10.2011, 23:55
Цитата Сообщение от sergeyotro Посмотреть сообщение
Надеюсь я её правильно понял.
ну почти... я имел ввиду написать обертку вокруг std::queue в которой push() и pop() защитить мьютексами.

твое решение тоже не плохое.
0
tanya234
08.04.2014, 18:51
а в какой среде вы разрабатывали?
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.04.2014, 18:51
Помогаю со студенческими работами здесь

Создать класс циклического буфера для целых чисел
задача - класс циклического буера для целых чисел. размер массива задаётся в конструкторе, элементы добавляются в конец и вынимаются из...

Копирование данных с одно циклического буфера в другой используя memcpy
Есть буфер который принимает два указателя на структуры циклических буферов, нужно что бы содержимое одного буфера скопировалось в другой с...

Реализация циклического алгоритма
Помогите пожалуйста! Мне нужно написать несколько программ, но получается не всё. Может кого заинтересует одно из заданий. Заранее огромное...

Реализация циклического алгоритма
Помогите понять как реализовать алгоритм. Допустим после пары шагов алгоритма есть условный оператор, который проверяет какое-либо условие....

Реализация циклического списка + решение задачи на подмножества
Здравствуйте, циклический список почти реализован, выводит не элементы строки только, а их адреса, не знаю, как исправить. ...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru