Форум программистов, компьютерный форум CyberForum.ru

не решается задача по параллельному программированию - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
liloracle
1 / 1 / 0
Регистрация: 23.04.2013
Сообщений: 11
26.09.2013, 18:21     не решается задача по параллельному программированию #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
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
 
#define CHAIRS 5
using namespace std;
int customers = 0;
int waiting = 0;
int barbers = 0;
 
HANDLE mutex;
HANDLE customerSemaphore;
HANDLE barberSemaphore;
 
//DWORD WINAPI customer(LPVOID);
//DWORD WINAPI barber(LPVOID);
 
DWORD WINAPI sleepstringka = rand()%200+250;
DWORD WINAPI sleepcustomer = rand()%2000+2500;
 
int const NUMBER_OF_CUSTOMERS = 20;
 
DWORD WINAPI barber(LPVOID)
{
    while (true)
    {
    if (waiting == 0)
    {
        cout << "\n Брадобрей решил поспать " << endl;
        WaitForSingleObject(customerSemaphore, INFINITE);
    }
    else
    {
        WaitForSingleObject(mutex, INFINITE);
        waiting--;
        ReleaseSemaphore(mutex,1,NULL);
        ReleaseSemaphore(barberSemaphore, 1, NULL);
        cout<< "\n Брадобрей стрижёт"<<endl;
        Sleep(sleepstringka);
    }
    }
}
 
DWORD WINAPI customer(LPVOID)
{
    WaitForSingleObject(mutex, INFINITE);
    if (waiting < CHAIRS)
    {
        Sleep(sleepcustomer);
        cout<<"\n Клиент занимает очередь"<<endl;
        waiting++;
        customers++;
        ReleaseSemaphore(customerSemaphore,1,NULL);
        ReleaseSemaphore(mutex,1,NULL);
        WaitForSingleObject(barberSemaphore, INFINITE);
    }
    else
    {
        Sleep(sleepcustomer);
        ReleaseSemaphore(mutex,1,NULL);
        cout<<"\n Клиент ушёл нестриженный"<<endl;
        ReleaseSemaphore(mutex,1,NULL);
    }
    Sleep(sleepcustomer);
    return 0;
}
 
void main()
{
    setlocale(LC_CTYPE, ".1251");  
    setlocale(LC_MONETARY, ".1251");
    mutex = CreateSemaphore(NULL, 1, 1, NULL);
    customerSemaphore = CreateSemaphore(NULL, 0,1,NULL);
    barberSemaphore = CreateSemaphore(NULL, 0,1, NULL);
    int f;
    HANDLE threadCus[NUMBER_OF_CUSTOMERS];
    HANDLE threadBar;
    DWORD cusThreadId;
    DWORD barThreadId;
    threadBar = CreateThread(NULL, 0, barber, (LPVOID)1,0,&barThreadId);
    for (int i = 0; i < NUMBER_OF_CUSTOMERS; ++i)
    {
        threadCus[i] = CreateThread(NULL,0,customer,(LPVOID)i,0, &cusThreadId);
    }
    
 
    cin >> f;
}
Добавлено через 45 секунд
80 просмотров, ни одного ответа.
Ребят никто не знает как дорешать или не видит ошибку??
Или всем лениво?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.09.2013, 18:21     не решается задача по параллельному программированию
Посмотрите здесь:

Про параллельному программированию. C++
C++ Задача по программированию
C++ Как решается эта сложная задача
Задача по программированию C++
Олимпиадная задача по программированию C++
C++ Разработать программу, реализующую алгоритм стека (20 элементов). Задача решается в двух вариантах: статическом и динамическом
C++ Задача по программированию. Цикл For
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Raali
587 / 291 / 19
Регистрация: 06.07.2013
Сообщений: 960
Завершенные тесты: 1
26.09.2013, 18:39     не решается задача по параллельному программированию #2
Цитата Сообщение от liloracle Посмотреть сообщение
Не получается решить задачу о спящем парикмахере...
каково условие задачи ?
liloracle
1 / 1 / 0
Регистрация: 23.04.2013
Сообщений: 11
26.09.2013, 18:57  [ТС]     не решается задача по параллельному программированию #3
Цитата Сообщение от Raali Посмотреть сообщение
каково условие задачи ?
ну нужно сделать приложение консольное на языке С++ которое реализует задачу о параллельном парикмахере (или брадобреи вроде еще она называется). Суть в чем: у нас есть поток клиентов, и один парикмахер, парикмахер стрижет клиентов, если парикмахер занят то клиент ожидает, если ожидающих клиентов больше какой то константы то клиент уходит не стриженым, если клиентов нету то парикмахер засыпает а пришедший клиент его будит.

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

делал в Visual Studio 2012
C++.Net
Убежденный
Системный программист
 Аватар для Убежденный
14440 / 6424 / 1015
Регистрация: 02.05.2013
Сообщений: 10,667
Завершенные тесты: 1
26.09.2013, 19:19     не решается задача по параллельному программированию #4
Цитата Сообщение от liloracle Посмотреть сообщение
Ребят никто не знает как дорешать или не видит ошибку??
Вижу целый ворох ошибок.
1) Нет проверки значений, которые возвращаются функциями.
2) Инкремент-декремент переменных - не атомарная операция.
3) Не обеспечена видимость переменных в разных потоках.
4) Называть семафор mutex-ом - это как минимум опасно.
5) ...

Но самая главная ошибка - код "размазан".
Не видно сущностей, таких как очередь, например, или захват/освобождение
объектов синхронизации. Поэтому он выглядит как каша (и работает, видимо, также).
liloracle
1 / 1 / 0
Регистрация: 23.04.2013
Сообщений: 11
26.09.2013, 19:49  [ТС]     не решается задача по параллельному программированию #5
Цитата Сообщение от Убежденный Посмотреть сообщение
Вижу целый ворох ошибок.
1) Нет проверки значений, которые возвращаются функциями.
2) Инкремент-декремент переменных - не атомарная операция.
3) Не обеспечена видимость переменных в разных потоках.
4) Называть семафор mutex-ом - это как минимум опасно.
5) ...

Но самая главная ошибка - код "размазан".
Не видно сущностей, таких как очередь, например, или захват/освобождение
объектов синхронизации. Поэтому он выглядит как каша (и работает, видимо, также).
1 - на что надо проверять значения эти?
2 - я так понял нужны функции up, down... где то было про это написано что это предложено Дейкстрой. вроде.
3 - переменные глобальные, видны везде вроде как.

все было бы просто и понятно если бы этот курс с этим заданием был после курса Параллельное программирование. А так они у нас идут параллельно . Мы только начали изучать параллельное программирование а по дисциплине Систем Реального Времени надо решать вот это.
Убежденный
Системный программист
 Аватар для Убежденный
14440 / 6424 / 1015
Регистрация: 02.05.2013
Сообщений: 10,667
Завершенные тесты: 1
26.09.2013, 19:59     не решается задача по параллельному программированию #6
Цитата Сообщение от liloracle Посмотреть сообщение
1 - на что надо проверять значения эти?
Ну например, CreateThread может вернуть NULL.
Это значит, что создать поток не удалось.
Качественно написанный код должен проверять и такие ситуации.

Цитата Сообщение от liloracle Посмотреть сообщение
2 - я так понял нужны функции up, down...
Используйте InterlockedIncrement/InterlockedDecrement. Они гарантируют,
что инкремент/декремент будет выполнен атомарно.

Цитата Сообщение от liloracle Посмотреть сообщение
3 - переменные глобальные, видны везде вроде как.
Да, но только не для многопоточных программ.
Доступ к разделяемым между потоками переменным должен быть специальным
образом обработан, иначе компилятор может сгенерировать такой код, где эти
переменные будут держаться в регистрах процессора и изменения в них не
будут видны из других потоков.

Тут самое простое - отметить такие переменные ключевым словом volatile.
Также можно использовать т.н. "барьеры" компилятора - _ReadWriteBarrier().

Цитата Сообщение от liloracle Посмотреть сообщение
все было бы просто и понятно если бы этот курс с этим заданием был после курса Параллельное программирование. А так они у нас идут параллельно
Понимаю.
Я имел в виду, что любую задачу, не обязательно связанную с многопоточностью/параллелизмом,
лучше оформлять четко, так, чтобы было рельефны видны все основные сущности, которые
в ней используются - клиент, парикмахер, очередь, объект синхронизации, флаг.
Разумеется, все это с опытом придет, если стараться
liloracle
1 / 1 / 0
Регистрация: 23.04.2013
Сообщений: 11
26.09.2013, 20:31  [ТС]     не решается задача по параллельному программированию #7
Цитата Сообщение от Убежденный Посмотреть сообщение
Ну например, CreateThread может вернуть NULL.
Это значит, что создать поток не удалось.
Качественно написанный код должен проверять и такие ситуации.



Используйте InterlockedIncrement/InterlockedDecrement. Они гарантируют,
что инкремент/декремент будет выполнен атомарно.



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

Тут самое простое - отметить такие переменные ключевым словом volatile.
Также можно использовать т.н. "барьеры" компилятора - _ReadWriteBarrier().



Понимаю.
Я имел в виду, что любую задачу, не обязательно связанную с многопоточностью/параллелизмом,
лучше оформлять четко, так, чтобы было рельефны видны все основные сущности, которые
в ней используются - клиент, парикмахер, очередь, объект синхронизации, флаг.
Разумеется, все это с опытом придет, если стараться
1,3 понял
во втором надо разобраться потому что то что вы мне сказали я слышу первый раз, честно.
с 4 согласен на 100 %. в итоге в отчет оформлю как нужно, для меня это черновик, единственное что на форуме люди сидят которым удобнее было бы разбираться с этим кодом если бы были еще комменты например =)
Убежденный
Системный программист
 Аватар для Убежденный
14440 / 6424 / 1015
Регистрация: 02.05.2013
Сообщений: 10,667
Завершенные тесты: 1
26.09.2013, 20:47     не решается задача по параллельному программированию #8
Цитата Сообщение от liloracle Посмотреть сообщение
1,3 понял
во втором надо разобраться потому что то что вы мне сказали я слышу первый раз
Инкремент/декремент в C++ - это неатомарная операция.
Если два или больше потоков параллельно инкрементируют переменную,
итоговое ее значение может отличаться от ожидаемого.
Происходит это потому, что инкремент даже на уровне CPU - операция
"трехфазная": а) прочитать значение; б) увеличить на 1; в) записать обратно.

Вот реальный пример "гонок" между потоками:
Есть переменная int, начальное значение 0. Первый поток прочел переменную
(старое значение, 0) и тут же второй сделал то же самое (у него тоже 0), потом
они оба увеличили считанное значение (у обоих теперь 1) и записали его обратно.
Получается, что в результате двухкратного инкремента значение переменной стало
равным 1. А должно быть 2.

Функция InterlockedIncrement, напротив, ставит барьер, запрещая другим CPU
модифицировать данные, пока не будет выполнен инкремент.
Поэтому с ней многопоточный инкремент всегда будет выдавать ожидаемый результат.
liloracle
1 / 1 / 0
Регистрация: 23.04.2013
Сообщений: 11
26.09.2013, 21:16  [ТС]     не решается задача по параллельному программированию #9
Цитата Сообщение от Убежденный Посмотреть сообщение
Инкремент/декремент в C++ - это неатомарная операция.
Если два или больше потоков параллельно инкрементируют переменную,
итоговое ее значение может отличаться от ожидаемого.
Происходит это потому, что инкремент даже на уровне CPU - операция
"трехфазная": а) прочитать значение; б) увеличить на 1; в) записать обратно.

Вот реальный пример "гонок" между потоками:
Есть переменная int, начальное значение 0. Первый поток прочел переменную
(старое значение, 0) и тут же второй сделал то же самое (у него тоже 0), потом
они оба увеличили считанное значение (у обоих теперь 1) и записали его обратно.
Получается, что в результате двухкратного инкремента значение переменной стало
равным 1. А должно быть 2.

Функция InterlockedIncrement, напротив, ставит барьер, запрещая другим CPU
модифицировать данные, пока не будет выполнен инкремент.
Поэтому с ней многопоточный инкремент всегда будет выдавать ожидаемый результат.
я понял о чем речь идет...
гонка данных нам так называли.

а сам код то в принципе верный?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.09.2013, 21:43     не решается задача по параллельному программированию
Еще ссылки по теме:

Задача о рюкзаке, решается ли она жадным алгоритмом? C++
C++ задача по программированию С++
Геометрическая задача по программированию (C++) C++
C++ Посоветуйте хорошую книгу по параллельному программированию на C++
C++ Задача с технокубка по программированию

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

Или воспользуйтесь поиском по форуму:
Убежденный
Системный программист
 Аватар для Убежденный
14440 / 6424 / 1015
Регистрация: 02.05.2013
Сообщений: 10,667
Завершенные тесты: 1
26.09.2013, 21:43     не решается задача по параллельному программированию #10
Цитата Сообщение от liloracle Посмотреть сообщение
Потоки работают не правильно судя по выводу.
Цитата Сообщение от liloracle Посмотреть сообщение
а сам код то в принципе верный?
Судя по первому сообщению - нет
Yandex
Объявления
26.09.2013, 21:43     не решается задача по параллельному программированию
Ответ Создать тему
Опции темы

Текущее время: 12:23. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru