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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
liloracle
1 / 1 / 0
Регистрация: 23.04.2013
Сообщений: 11
#1

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

26.09.2013, 18:21. Просмотров 1122. Ответов 9
Метки нет (Все метки)

Всех приветствую.
Третью неделю пытаюсь сделать лабу. Не получается решить задачу о спящем парикмахере...
Собственно кто может ПОМОЧЬ допилить лабу?
Потоки работают не правильно судя по выводу.
Не очень понимаю как отлаживать такие приложения, потоки прыгают не уловить сути.


Код прикладываю, разумеется.
Буду очень благодарен.

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 просмотров, ни одного ответа.
Ребят никто не знает как дорешать или не видит ошибку??
Или всем лениво?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.09.2013, 18:21
Здравствуйте! Я подобрал для вас темы с ответами на вопрос не решается задача по параллельному программированию (C++):

Литература по параллельному программированию. - C++
Здравствуйте я новичок на этом форуме и не смог найти раздел параллельного программирования... поэтому я написал здесь так как нужно...

Про параллельному программированию. - C++
Могут ли два потока одновременно обращаться к одному и тому же участку памяти на чтение?

Посоветуйте хорошую книгу по параллельному программированию на C++ - C++
Чтоб твердый акцент был сделан на теорию. После изучения стандарта сразу хочу вступить к изучению параллелизма.

Как решается эта сложная задача - C++
Как решить? Если у массива А(40) есть элемент, равный В, то отсортировать элементы, находящиеся после него по убыванию сортировкой...

Задача о рюкзаке, решается ли она жадным алгоритмом? - C++
Здравствуйте. Задали сделать задачу о рюкзаке, используя жадину. Даны вес и стоимость предметов. Набить рюкзак предметами, чтобы...

Разработать программу, реализующую алгоритм стека (20 элементов). Задача решается в двух вариантах: статическом и динамическом - C++
Разработать программу, реализующую алгоритм стека (20 элементов). Задача решается в двух вариантах: статическом (на основе массива...

9
Raali
623 / 327 / 34
Регистрация: 06.07.2013
Сообщений: 1,062
Завершенные тесты: 1
26.09.2013, 18:39 #2
Цитата Сообщение от liloracle Посмотреть сообщение
Не получается решить задачу о спящем парикмахере...
каково условие задачи ?
0
liloracle
1 / 1 / 0
Регистрация: 23.04.2013
Сообщений: 11
26.09.2013, 18:57  [ТС] #3
Цитата Сообщение от Raali Посмотреть сообщение
каково условие задачи ?
ну нужно сделать приложение консольное на языке С++ которое реализует задачу о параллельном парикмахере (или брадобреи вроде еще она называется). Суть в чем: у нас есть поток клиентов, и один парикмахер, парикмахер стрижет клиентов, если парикмахер занят то клиент ожидает, если ожидающих клиентов больше какой то константы то клиент уходит не стриженым, если клиентов нету то парикмахер засыпает а пришедший клиент его будит.

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

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

Но самая главная ошибка - код "размазан".
Не видно сущностей, таких как очередь, например, или захват/освобождение
объектов синхронизации. Поэтому он выглядит как каша (и работает, видимо, также).
0
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 - переменные глобальные, видны везде вроде как.

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

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

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

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

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



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



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

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



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

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

Функция InterlockedIncrement, напротив, ставит барьер, запрещая другим CPU
модифицировать данные, пока не будет выполнен инкремент.
Поэтому с ней многопоточный инкремент всегда будет выдавать ожидаемый результат.
0
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
модифицировать данные, пока не будет выполнен инкремент.
Поэтому с ней многопоточный инкремент всегда будет выдавать ожидаемый результат.
я понял о чем речь идет...
гонка данных нам так называли.

а сам код то в принципе верный?
0
Убежденный
Системный программист
Эксперт С++
15631 / 7140 / 1129
Регистрация: 02.05.2013
Сообщений: 11,582
Записей в блоге: 1
Завершенные тесты: 1
26.09.2013, 21:43 #10
Цитата Сообщение от liloracle Посмотреть сообщение
Потоки работают не правильно судя по выводу.
Цитата Сообщение от liloracle Посмотреть сообщение
а сам код то в принципе верный?
Судя по первому сообщению - нет
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.09.2013, 21:43
Привет! Вот еще темы с ответами:

Задача по программированию - C++
Составить программу упорядочения элементов по убыванию во втором столбце матрицы A(N,N).

задача по программированию С++ - C++
Помогите пожалуйста написать задачу на C++ по фото . Задача B2

Задача по программированию - C++
Друзья, помогите с задачей по программированию. Дан массив t из 10 элементов, в каждом находится структура x в которой соответственно...

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


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

Или воспользуйтесь поиском по форуму:
10
Yandex
Объявления
26.09.2013, 21:43
Ответ Создать тему
Опции темы

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