Russian Qt Forum
Ноябрь 23, 2024, 03:26 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 ... 4 5 [6] 7 8   Вниз
  Печать  
Автор Тема: Использование QWaitCondition  (Прочитано 74710 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #75 : Декабрь 25, 2012, 10:18 »

Вместо побудки свободных потоков у вас опять таки идёт побудка какого то "определённого" количества.
Читаем первоисточник
Цитировать
For example, let's suppose that we have three tasks that should be performed whenever the user presses a key.
Как мы видим, речь идет о строго определенном, конкретном числе задач (3). Это нормальный, корректный подход к multithreaded, Мы не можем и не должны рассчитывать на то что какие-то нитки нас ждут, но мы железно гарантируем что все 3 будут (так или иначе) выполнены.

Управляющий будит рабочих только после полной их отработки?
Не врубаетесь в суть. Корректно "после того как все предыдущие задачи завершены". Это совсем не значит что нитка сделавшая задачу "отработала" и уже ждет на wait. Я умышленно выделил это место в ф-цию CreateTask которая может быть получена через copy/paste из исходного примера, но все-таки одну строчку нужно подправить.

Теперь такой момент. Автор может публиковать свое решение в том виде в котором считает нужным. Напр я считаю необходимым выделить HandleTask и CreateTask чтобы четко показать структуру алгоритма. Если Вас это не устраивает - это Ваши проблемы, но настойчивые требования все разжевать, положить в рот и помочь проглотить здесь неуместны.

Ладно, другой, более веселый разговор (из-за которого собственно я и вернулся в тему)
Но предложенный вами вариант решение проблемы с numTask - магическое число и это крайне плохое решение. Любой программист с опытом это подтвердит.
Зачем же прятаться за некоего "программиста с опытом"? Улыбающийся Есть производитель(и), есть потребитель(и). Если производитель ничего не произвел - потребителю нечего потреблять. numTask - число произведенных товаров. Пусть магическое если хотите. Но как Вы представляете обойтись без него? Типа "пусть те потребители которые сейчас ничего не потребляют еще чего-то(?) потребят" - чушь собачья  Улыбающийся

Далее Вы рассказываете о Вашей задаче в которой пропуск исходных данных допустим, и даже необходим. Это ассоциируются с теорией Эйнштейна, искривлением пр-ва и времени. А для нормального программиста утерянные данные - это просто баг за который можно получить и который надо исправлять. Поэтому если Вы хотели поговорить о чем-то особенном, изысканном, извращенном - место этому в отдельной теме.

А главное: если Вы хотите чего-то доказать - так ДЕЛАЙТЕ это. Предъявите Ваше решение, кратко поясните чем оно лучше другого (напр моего). И все всем станет ясно автоматычно. А так чем больше Вы стараетесь уверить окружающих в собственной крутизне - тем меньше верится.

Так что же все-таки мешает нашему танцору (кроме воды)?  Улыбающийся
Записан
Dancing_on_water
Гость
« Ответ #76 : Декабрь 26, 2012, 09:36 »

Цитировать
А главное: если Вы хотите чего-то доказать
Изыди бес, нечистый своими помыслами! Покинь тело человека! До коли память короткая, то я тебе говорил, что здесь не ярмарка тщеславия. И я здесь появился не для того, чтобы что-то доказывать и красоваться. Также, если память коротка, обсуждение началось с выписанной мной из доки схемы. Так, если что-то и доказывал, так это ты.

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

Если продолжаешь упрямиться. То мой тебе совет: почитай по методы синхронизации про примитивы, про то как устроены потоки. Придумайте или найди в opensource себе задачу. Этот тред и твой пост - это все от недостатка опыта решения реальных, а не школьных задач.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #77 : Декабрь 26, 2012, 12:23 »

Изыди бес,
Типичный пост написанный в порыве горячности и неумения контролировать себя. Ничего, в следующий раз перед тем как бросаться словами подумаете что могут попросить за них ответить  Улыбающийся
Записан
Kosmonit
Гость
« Ответ #78 : Июль 16, 2013, 10:59 »

Парни подмогните разобраться, начинаю разбираться с многопоточным программирование, это для меня в новинку.
Читаю уже 4й день Ваш пост и не могу воткнуть что и как, где пробои, в чем ошибки примеров, как баран на новые ворота.
Набросал код своего  Producer и Consumer.
Посмотрите есть ли ошибки или все правильно я понял и сделал свой пример.
Global var:
Код:
const int dataSize = 200;
const int bufSize = 10;
std::list<int> listTask;
std::list<QString> rezult;

QMutex mutexRezult;
QMutex mutex;
QWaitCondition bufNotFull;
QWaitCondition bufNotEmpty;

CProducer:
Код:
	void run()
{
for (int i = 0; i < dataSize; i++)
{
mutex.lock(); // Блокирем мютекс
while (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный

listTask.push_back(i); // Генерируем задачу

bufNotEmpty.wakeAll(); // Побудка что буфер не пустой
mutex.unlock(); // Разблокируем мютекс
}
}

CConsumer:
Код:
	void run()
{
for (int i = 0; i < dataSize; i++)
{
mutex.lock(); // Блокируем мютекс
while (listTask.size() == 0) // Если буфер пустой
bufNotEmpty.wait(&mutex); // Ждем побудки буфер не пустой

int task = *listTask.begin(); // Получаем задачу
listTask.pop_front();

bufNotFull.wakeAll(); // Побудка буфер не полный
mutex.unlock(); // Разблокируем мютекс

msleep(1 + rand()%100); // Обрабатываем задачу

// Выводим результат работы
QString s = tr("Thread = %1 *** Task = %2").
arg(m_numThread).
arg(task);
mutexRezult.lock();
rezult.push_back(s);
mutexRezult.unlock();
}
}
   

main:
   
Код:
	CConsumer consumer1(1);
CConsumer consumer2(2);
CConsumer consumer3(3);
CProducer producer;

consumer1.start();
   consumer2.start();
   consumer3.start();
producer.start();

Под конец кода у меня такой вопрос?
Нельзя ли заменять цикл:
while (listTask.size() == 0) на if(listTask.size() == 0)
и
while (listTask.size() == bufSize) на if (listTask.size() == bufSize)
и в чем разница.
            
« Последнее редактирование: Июль 16, 2013, 11:08 от Kosmonit » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #79 : Июль 16, 2013, 11:12 »

...или все правильно я понял...
Все правильно вы поняли.

Под конец кода у меня такой вопрос?
Нельзя ли заменять цикл:
while (listTask.size() == 0) на if(listTask.size() == 0)
и
while (listTask.size() == bufSize) на if (listTask.size() == bufSize)
и в чем разница.
Чем мешает цикл? Улыбающийся
Смотрите, мы добавили одну задачу в очередь и будим все нити. Просыпается первая простаивающая и забирает это задание из очереди, просыпается вторая простаивающая, а задачи и нет. Тогда нить начнет выполнять тело цикла, т.е. заснет на wait опять.
Записан
Kosmonit
Гость
« Ответ #80 : Июль 16, 2013, 11:21 »

...или все правильно я понял...
Все правильно вы поняли.

Под конец кода у меня такой вопрос?
Нельзя ли заменять цикл:
while (listTask.size() == 0) на if(listTask.size() == 0)
и
while (listTask.size() == bufSize) на if (listTask.size() == bufSize)
и в чем разница.
Чем мешает цикл? Улыбающийся
Смотрите, мы добавили одну задачу в очередь и будим все нити. Просыпается первая простаивающая и забирает это задание из очереди, просыпается вторая простаивающая, а задачи и нет. Тогда нить начнет выполнять тело цикла, т.е. заснет на wait опять.

1. Ага, ок
2. Т.е. while все таки нужен?
3. wakeAll - все потоки одновременно будятся? И выходит кто первый взял задачу тот и король, а все остальные в цикл опять попадают, потому что нет задач? Правильно?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #81 : Июль 16, 2013, 11:28 »

1. Ага, ок
2. Т.е. while все таки нужен?
3. wakeAll - все потоки одновременно будятся? И выходит кто первый взял задачу тот и король, а все остальные в цикл опять попадают, потому что нет задач? Правильно?
Да.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #82 : Июль 16, 2013, 12:09 »

wakeAll - все потоки одновременно будятся? И выходит кто первый взял задачу тот и король, а все остальные в цикл опять попадают, потому что нет задач? Правильно?
Нет, будятся только те что ждут на WaitCondition, для других wake не имеет эффекта. Поэтому и нужен while. Поскольку Вы создаете 1 задачу, то аккуратнее wakeOne.
Записан
Kosmonit
Гость
« Ответ #83 : Июль 16, 2013, 12:42 »

Ок, спасибо, буду разбираться, если что отпишусь не судите строго.
Записан
Kosmonit
Гость
« Ответ #84 : Июль 16, 2013, 13:01 »

Нет, будятся только те что ждут на WaitCondition, для других wake не имеет эффекта. Поэтому и нужен while.
Еще разок можно прокомментировать этот момент?
Т.е. если поток прерван в другом месте, то WaitCodition его не разбудит это понятно.
А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Воткните стрелочки где код остановлен в мой код для пояснинения, никак не могу уловить сути.

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #85 : Июль 16, 2013, 14:29 »

Т.е. если поток прерван в другом месте, то WaitCodition его не разбудит это понятно.
Прерван (вытеснен) или нет - неважно, если он не успел войти в ожидание то эффект поюудки нулевой

А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Воткните стрелочки где код остановлен в мой код для пояснинения, никак не могу уловить сути.
Ну вот допустим
Код
C++ (Qt)
if (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный
 
Да, ушли на wait, да, проснулись по wake. Но ведь нет никаких гарантий что когда проснулись - в буфере есть место. Напр другой проснулся раньше и успел это место заполнить. Можно опять проверить if'ом но while лучше

Edit: смысл в том что wait освобождает мутекс до тех пор пока управление не вернется - а значит ситуация выходит из-под контроля
« Последнее редактирование: Июль 16, 2013, 14:32 от Igors » Записан
Kosmonit
Гость
« Ответ #86 : Июль 16, 2013, 15:45 »

Т.е. если поток прерван в другом месте, то WaitCodition его не разбудит это понятно.
Прерван (вытеснен) или нет - неважно, если он не успел войти в ожидание то эффект поюудки нулевой

А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Воткните стрелочки где код остановлен в мой код для пояснинения, никак не могу уловить сути.
Ну вот допустим
Код
C++ (Qt)
if (listTask.size() == bufSize) // Если буфер полный
bufNotFull.wait(&mutex); // Ждем побудки буфер не полный
 
Да, ушли на wait, да, проснулись по wake. Но ведь нет никаких гарантий что когда проснулись - в буфере есть место. Напр другой проснулся раньше и успел это место заполнить. Можно опять проверить if'ом но while лучше

Edit: смысл в том что wait освобождает мутекс до тех пор пока управление не вернется - а значит ситуация выходит из-под контроля

Все, спасибо огромное, кажется начинаю втыкать!!!
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #87 : Июль 16, 2013, 16:08 »

Нет
Да. Потому что это:
будятся только те что ждут на WaitCondition
и так очевидно. Улыбающийся

А вот с while? Не могу воткнуть почему if нельзя сделать? Наверно if можно воткнуть если один поток генерит задачи, а другой обрабатывает а если несколько, то нельзя?
Смотрите, нить уснула на wait, когда ее будит wake, то управление получит она же, т.е. мы возвращаемся в wait.
При этом никто не гарантирует, что задания еще есть и их не выбрали более "быстрые" нитки. Значит, нам нужно после wait, еще раз удостовериться, что задания остались и если их нет, то снова заснуть на wait. Вот эта петля и решает эти действия.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #88 : Июль 17, 2013, 09:44 »

Смотрите, нить уснула на wait, когда ее будит wake, то управление получит она же,
Это бесспорно, но вот тут есть одно подозрительное место
Код
C++ (Qt)
bufNotEmpty.wakeAll();
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
а др нитка
Код
C++ (Qt)
bufNotEmpty.waitl(&mutex);
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
А как мы знаем только одна нитка может владет мутексом. В каком же порядке они им овладевают? Или выходит что пробуждение случится только после того как будящий отдаст мутекс? И если будятся несколько, то понятно что порядок произволен, но может ли пробудившийся рассчитывать на то что остальные или еще спят, или уже отстрелялись и опять ждут на мутексе?
Записан
Kosmonit
Гость
« Ответ #89 : Июль 17, 2013, 10:29 »

Смотрите, нить уснула на wait, когда ее будит wake, то управление получит она же,
Это бесспорно, но вот тут есть одно подозрительное место
Код
C++ (Qt)
bufNotEmpty.wakeAll();
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
а др нитка
Код
C++ (Qt)
bufNotEmpty.waitl(&mutex);
<--- сейчас эта нитка владеет мутексом
mutex.unlock();
 
А как мы знаем только одна нитка может владет мутексом. В каком же порядке они им овладевают? Или выходит что пробуждение случится только после того как будящий отдаст мутекс? И если будятся несколько, то понятно что порядок произволен, но может ли пробудившийся рассчитывать на то что остальные или еще спят, или уже отстрелялись и опять ждут на мутексе?
Я код реализации qwaitcondition_win.cpp посмотрел, мне кажется пробуждение случается на функции:
QWaitCondition::wakeAll()...SetEvent(current->event); - на ней, когда событие взводится.
Непонимающий
А в чем слабость выше приведенного Вами кода?
Записан
Страниц: 1 ... 4 5 [6] 7 8   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.236 секунд. Запросов: 22.