![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| Agentx86 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 110 Регистрация: 27.4.2006 Репутация: нет Всего: нет |
В программе есть несколько потоков которые делают какието вычисления. Надо когда все потоки закончат вычисления просумировать все данные и чтото выполнить. Вот я для этого использовал функцию WaifForMultiplyObject. Эта функция ждет завершение всех поток и только после этого программа начинает работать дальше. Как можно сделать тоже самое используя синхронизацию потоков, но не используя данную функцию?
|
|||
|
||||
| Cycle |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 59 Регистрация: 1.12.2007 Репутация: нет Всего: 3 |
Каждому процессу раздаешь по мутексу, по окнчании работы каждый процесс освобождает мутекс. Процесс, который должен просуммировать все данные, должен попытатся захватить все мутексы. Ему это удастся, когда все остальные процессы освободят свои мутексы.
Также вроде бы подобное можно промутить с критическими секциями. Потому как EnterCriticalSection - это аналог захвата мутекса, а LeaveCriticalSection - это аналог его освобождения. Надеюсь, что с критическими секциями я ничего не напутал В MSDN написано, что
Поэтому, если эта операция у тебя происходит в цикле, то использование критических секций будет работать в 2-3 раза быстрее, чем мутексы. Проверено на практике |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 33 Всего: 183 |
Ведь сам же ниже привел цитату "... except ". Не годятся критические секции для ожидания - только для простой синхронизации доступа к данным. Простой в том смысле, что доступ будет разрешен только одному потоку, и не важно, что он там делает. Agentx86, синхронизация, но без Wait-функций - это примерно то же самое, что манная каша, но без манки - не бывает. То, что ты сделал - наилучший способ - ждать завершения всех потоков, засунув список хандлов в WaitForMultipleObject. Нафиг тут мьютексы и прочая не нужны. Тем более, что и их через Wait ждать придется - больше нечем. Т.е. нет, пардон, можно все тоже самое написать не через объекты ядра, а на коленках, скажем, заведя глобальную переменную (счетчик работающих потоков) и пусть каждый поток перед завершением ее декрементирует... А в основном замутить бесконечный цикл и проверять значение этой переменной... Пальчики оближешь, до чего изящное решение... Это хочешь? -------------------- ... |
|||
|
||||
| Agentx86 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 110 Регистрация: 27.4.2006 Репутация: нет Всего: нет |
Все задача решена. А это не моя прихоть так извращаться. Преподы запаривают вопросами - "Я хочу, чтобы вы сделали тоже самое, но не используя эту функцию"
|
|||
|
||||
| Cycle |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 59 Регистрация: 1.12.2007 Репутация: нет Всего: 3 |
Earnest, нельзя недооценивать возможности критических секций. Ещё раз с акцентирую фразу:
Т.е. если потоки выполня.тся в пределах одного процесса, то предпочтение нужно отдавать именно критическим секциям, т.к.
И как показала практика в 2-3 раза. А как именно задачу Agentx86 реализовать через мутексы/критические секции я написал выше. P.S. Я как раз тот студент который удовлетворял прихоти преподов и с ними согласен, так как программист должен думать гибко |
||||
|
|||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 33 Всего: 183 |
Cycle,
А кто их недооценивает? Да, ты прав, можно "раздать" каждому потоку по критической секции, поставив в начале-конце потоковой функции Enter\Leave. Но, чтобы основной поток дождался освобождения всех секций, ему нужно выполнить Enter в эти критические секции - отдельно в каждую - видимо, в цикле... На мой взгляд, данное решение по своей кривизне аналогично предложенному мной "решению" с глобальным счетчиком. Разве что удовлетворение требования препода может оправдать такое. Но заметь, об этом автор сказал только потом... А почему он не хочет использовать Wait - да мало ли, может ему казалось, что есть решение лучше. Что касается использования мьютексов, то их, во-первых, их все-таки придется ждать с помощью Wait, а во-вторых - мьютексы в данном контексте избыточны, ибо есть хандлы самих потоков. Насчет гибкости... не знаю, где тут гибкость, если человек сразу нашел нормальное решение, миновав глупости, которые, возможно, от него ждал преподаватель. Да, я понимаю, если препод получит от студента решение задачи в лоб, но не самое оптимальное - можно сказать - а подумай-ка, нельзя ли сделать лучше, и подсказать - не используй это, а используй то... А так, он требует, вместо оптимального решения - решение через ж. коленом и, скорее всего, это вовсе не единичный случай. Т.е. как-то жить с этим приходится, но уж говорить, что это правильно - увольте... Что касается твоего замечания насчет предпочтения мьютексу критической секции в рамках одного процесса - тоже не соглашусь. Т.е. далеко не всегда. Есть вещи, которые можно сделать с помощью мьютекса и нельзя - с помощью секции. Да хотя бы защита от зацикливания или зависания потока - функции Wait можно дать timeout, по окончании которого поток можно просто прибить, а после вызова Enter назад дороги нет... Добавлено через 7 минут и 43 секунды Да, еще: запустив все потоки, основной поток сразу начинает ждать освобождения что мьютексов, что критических секций. И где гарантия, что его вызов не окажется первым (т.е. именно он захванит объект, не дав этого сделать потоку)? Такое гораздо чаще встречается на практике, чем хотелось бы думать. Т.е. защититься от этого, конечно, можно, воодя дополнительные механизмы, но это опять лишние усложнения. А без них - это вовсе не решение, т.к. работает не стопроцентно. -------------------- ... |
|||
|
||||
| Agentx86 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 110 Регистрация: 27.4.2006 Репутация: нет Всего: нет |
Преподу не понравилось, что я выполнил лабу неиспользовав синхронизацию потоков.
|
|||
|
||||
| Simargl |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 12.12.2007 Репутация: нет Всего: нет |
Earnest, пардон, не вижу надобности в цикле.
во вторых описанная ситуация когда поток не выходит из крит секции а другой пытается туда влезть, называется deadlock и вызывается исключительно кривостью рук программиста. А в рамках процесса правильнее использовать крит секции, соглашусь с Cycle, с вопросом почему - к Рихтеру. |
|||
|
||||
| Agentx86 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 110 Регистрация: 27.4.2006 Репутация: нет Всего: нет |
Simargl, Ты тут чтото сказал про криворукость рук. Значит у меня кривые руки. Предложи свой вариант. Причем нельзя вызывать WaitForMultiply или пять раз WaitForSingleObject.
Надо синхронизировать первые 5 потоков а WaitForSingleObject может быть вызвана один раз. |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: нет Всего: 101 |
Без WaitFor... ничего не выйдет. Критические секции "вроде бы" позволяют, но где гарантия, что вызывающая программа не попытается войти в секцию раньше вызываемого потока? Sleep() в вызывающей увеличивает шансы, но не дает гарантии, а следовательно дает иллюзию. И "нормально работающая" программа на 101м вызове заработает не так.
Agentx86, мне кажется, тут спутаны два понятия: синхронизация выполнения потоков и синхронизация доступа к объекту из разных потоков. В итоге, естесстно, все сводится к одним и тем же механизмам, разница только в ходе размышлений. Но: для доступа к объекту весьма подходят критические секции. С их помощью нельзя строго установить очередность, но обеспечивается монопольность доступа. Для синхронизации выполнения кто-то кого-то должен подождать, т.е. обязателен Wait. Добавлено через 1 минуту и 51 секунду Интересно, как выглядит правильное решение без wait с точки зрения препода. |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 8 Всего: 154 |
критические секции позволяют синхронизировать доступ к объекту, причем они обеспечивают только эксклюзивный доступ к объекту, при этом нет возможности обработать ситуацию, когда поток в котором захвачена секция, забыл ее разлочить))
мютекс, более гибок, можно например просто проверить его состояние, а не ждать, установить timeout на ожидание. Мютекс может быть именованным, а значит его можно использовать для синхронизации процессов. Еще есть разновидность Wait функций, которые просыпаются по сообщению, тут вообще критические секции не применимы.
в целом критические секции лучше применять для синх. доступа к данным(они для этого и сделаны), а мютексы(семафоры, события, таймеры...) - для синхронизации потоков(процессов). Это сообщение отредактировал(а) Lazin - 13.12.2007, 09:01 |
|||
|
||||
| Nastya |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 27.3.2002 Где: Мариуполь Репутация: 3 Всего: 44 |
Вааще не поняла чем не нравится WaitFor... и зачем что-то еще изобретать.
Единственное что если при расчетах идет обращения к одним и тем же данным это аккуратно надо синхронизировать. -------------------- Что бы понять рекурсию, надо понять рекурсию "Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор |
|||
|
||||
| Agentx86 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 110 Регистрация: 27.4.2006 Репутация: нет Всего: нет |
Если честно я тоже не мог понять препопада и хотябы один раз WaitForSingleObject вызвать надо это без вариантов. А идея какая. Название лабы "Синхронизация потоков", а я её сделал не используя объекты синхронизации. Вот он и начал "А вот я хочу убрать отсюда функцию WaitForMultiplyObject". Я ему говорю "А я поставлю 5 функций WaitForSingleObject". Препод ответчает "Мне так тоже неподойдет. Например первый поток будет работать дольше всего. Мы будет сначала ждать его, а пото только другие которые уже завершились. Потеря времени". Хотя вариант который предложили с критичискими секциями не будет быстрее чем 5 WaitForSingleObject. Он будет работать также. Потомучто мы в шесток потоке пытаемся сделать EnterCriticalSection сначала в первый поток, потом во второй............. .
Как решить эту задачу, чтобы она выполнялась по скорости как c WaitForMultiplyObject и не используя эту функцию я не знаю. Мне кажется препод сам не знает. Я у него на защите лабы поинтерисуюсь. p.s. Nastya не употребляй слова паразиты. Кстати мы знакомы. |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 1 Всего: 207 |
Agentx86,
N потоков можно заменить на N - 1 поток (поток, порождающий потоки, может заменить один из них) это увеличит производительность Добавлено через 5 минут и 16 секунд
после того, как основной поток завершил выполнение своей функции, он уже может приступать к суммированию, если хотя бы один другой поток к этому моменту уже завершил выполнение -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: нет Всего: 101 |
Понятно. Препод хотел мьютексов, но не продумал ни задание, ни линию поведения
Имхо число WaitFor на скорость не влияет. В том смысле, что общее время работы в любом случае - время работы самого продолжительного потока. Вот если действительно начинать суммировать результаты уже завершенных потоков, как предложил MAKCim - другое дело. |
|||
|
||||
| Stranger2048 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 40 Регистрация: 21.12.2007 Репутация: нет Всего: нет |
Ребят, а почему события не попробовать?.. Установить его, когда все потоки завершат свою работу, а поток, котору нужно делать результирующие вычисления, будет как раз этого события и ждать, естественно через один вызов WaitForSingleObject.
Ну это как вариант для удовлетворения запросов препода. |
|||
|
||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |