Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация потоков 
:(
    Опции темы
Agentx86
Дата 8.12.2007, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 110
Регистрация: 27.4.2006

Репутация: нет
Всего: нет



В программе есть несколько потоков которые делают какието вычисления. Надо когда все потоки закончат вычисления просумировать все данные и чтото выполнить. Вот я для этого использовал функцию WaifForMultiplyObject. Эта функция ждет завершение всех поток и только после этого программа начинает работать дальше. Как можно сделать тоже самое используя синхронизацию потоков, но не используя данную функцию?
PM MAIL   Вверх
Cycle
Дата 8.12.2007, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 1.12.2007

Репутация: нет
Всего: 3



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

Также вроде бы подобное можно промутить с критическими секциями. Потому как EnterCriticalSection - это аналог захвата мутекса, а LeaveCriticalSection - это аналог его освобождения. Надеюсь, что с критическими секциями я ничего не напутал smile

В MSDN написано, что
Цитата

Critical section objects provide synchronization similar to that provided by mutex objects, except that critical section objects can be used only by the threads of a single process. Event, mutex, and semaphore objects can also be used in a single-process application, but critical section objects provide a slightly faster, more efficient mechanism for mutual-exclusion synchronization.

Поэтому, если эта операция у тебя происходит в цикле, то использование критических секций будет работать в 2-3 раза быстрее, чем мутексы. Проверено на практике smile
PM MAIL   Вверх
Earnest
Дата 11.12.2007, 21:09 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(Cycle @  9.12.2007,  00:33 Найти цитируемый пост)
Потому как EnterCriticalSection - это аналог захвата мутекса, а LeaveCriticalSection - это аналог его освобождения. Надеюсь, что с критическими секциями я ничего не напутал 

Ведь сам же ниже привел цитату "... except ". 
Не годятся критические секции для ожидания - только для простой синхронизации доступа к данным. Простой в том смысле, что доступ будет разрешен только одному потоку, и не важно, что он там делает.

Agentx86, синхронизация, но без Wait-функций - это примерно то же самое, что манная каша, но без манки - не бывает.
То, что ты сделал - наилучший способ - ждать завершения всех потоков, засунув список хандлов в WaitForMultipleObject. Нафиг тут мьютексы и прочая не нужны. Тем более, что и их через Wait ждать придется - больше нечем.

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


--------------------
...
PM   Вверх
Agentx86
Дата 11.12.2007, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 110
Регистрация: 27.4.2006

Репутация: нет
Всего: нет



Все задача решена. А это не моя прихоть так извращаться. Преподы запаривают вопросами - "Я хочу, чтобы вы сделали тоже самое, но не используя эту функцию"
PM MAIL   Вверх
Cycle
  Дата 12.12.2007, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 1.12.2007

Репутация: нет
Всего: 3



Earnest, нельзя недооценивать возможности критических секций. Ещё раз с акцентирую фразу: 
Цитата

Critical section objects provide synchronization similar to that provided by mutex objects, except that critical section objects can be used only by the threads of a single process.

Т.е. если потоки выполня.тся в пределах одного процесса, то предпочтение нужно отдавать именно критическим секциям, т.к. 
Цитата

critical section objects provide a slightly faster

И как показала практика в 2-3 раза.
А как именно задачу Agentx86 реализовать через мутексы/критические секции я написал выше.
P.S. Я как раз тот студент который удовлетворял прихоти преподов и с ними согласен, так как программист должен думать гибко smile
PM MAIL   Вверх
Earnest
Дата 12.12.2007, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Cycle, 
Цитата(Cycle @  12.12.2007,  11:52 Найти цитируемый пост)
Earnest, нельзя недооценивать возможности критических секций. 

А кто их недооценивает?
Да, ты прав, можно "раздать" каждому потоку по критической секции, поставив в начале-конце потоковой функции Enter\Leave.
Но, чтобы основной поток дождался освобождения всех секций, ему нужно выполнить Enter в эти критические секции - отдельно в каждую - видимо, в цикле... На мой взгляд, данное решение по своей кривизне аналогично предложенному мной "решению" с глобальным счетчиком. Разве что удовлетворение требования препода может оправдать такое. Но заметь, об этом автор сказал только потом... А почему он не хочет использовать Wait - да мало ли, может ему казалось, что есть решение лучше.
Что касается использования мьютексов, то их, во-первых, их все-таки придется ждать с помощью Wait, а во-вторых - мьютексы в данном контексте избыточны, ибо есть хандлы самих потоков.

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

Что касается твоего замечания насчет предпочтения мьютексу критической секции в рамках одного процесса - тоже не соглашусь. Т.е. далеко не всегда. Есть вещи, которые можно сделать с помощью мьютекса и нельзя - с помощью секции. Да хотя бы защита от зацикливания или зависания потока - функции Wait можно дать timeout, по окончании которого поток можно просто прибить, а после вызова Enter назад дороги нет...

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


--------------------
...
PM   Вверх
Agentx86
Дата 12.12.2007, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 110
Регистрация: 27.4.2006

Репутация: нет
Всего: нет



Преподу не понравилось, что я выполнил лабу неиспользовав синхронизацию потоков.
PM MAIL   Вверх
Simargl
Дата 12.12.2007, 23:57 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 12.12.2007

Репутация: нет
Всего: нет



Earnest, пардон, не вижу надобности в цикле.
во вторых описанная ситуация когда поток не выходит из крит секции а другой пытается туда влезть, называется deadlock и вызывается исключительно кривостью рук программиста. А в рамках процесса правильнее использовать крит секции, соглашусь с Cycle, с вопросом почему - к Рихтеру.

PM MAIL   Вверх
Agentx86
Дата 13.12.2007, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 110
Регистрация: 27.4.2006

Репутация: нет
Всего: нет



Simargl, Ты тут чтото сказал про криворукость рук. Значит у меня кривые руки. Предложи свой вариант. Причем нельзя вызывать WaitForMultiply или пять раз WaitForSingleObject.
Надо синхронизировать первые 5 потоков а WaitForSingleObject может быть вызвана один раз.
PM MAIL   Вверх
baldina
Дата 13.12.2007, 03:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: нет
Всего: 101



Без WaitFor... ничего не выйдет. Критические секции "вроде бы" позволяют, но где гарантия, что вызывающая программа не попытается войти в секцию раньше вызываемого потока? Sleep() в вызывающей увеличивает шансы, но не дает гарантии, а следовательно дает иллюзию. И "нормально работающая" программа на 101м вызове заработает не так.

Agentx86, мне кажется, тут спутаны два понятия: синхронизация выполнения потоков и синхронизация доступа к объекту из разных потоков. В итоге, естесстно, все сводится к одним и тем же механизмам, разница только в ходе размышлений. 
Но: для доступа к объекту весьма подходят критические секции. С их помощью нельзя строго установить очередность, но обеспечивается монопольность доступа. Для синхронизации выполнения кто-то кого-то должен подождать, т.е. обязателен Wait.

Добавлено через 1 минуту и 51 секунду
Интересно, как выглядит правильное решение без wait с точки зрения препода.
PM MAIL   Вверх
Lazin
Дата 13.12.2007, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



критические секции позволяют синхронизировать доступ к объекту, причем они обеспечивают только эксклюзивный доступ к объекту, при этом нет возможности обработать ситуацию, когда поток в котором захвачена секция, забыл ее разлочить))
мютекс, более гибок, можно например просто проверить его состояние, а не ждать, установить timeout на ожидание. Мютекс может быть именованным, а значит его можно использовать для синхронизации процессов. Еще есть разновидность Wait функций, которые просыпаются по сообщению, тут вообще критические секции не применимы.
Код

DOUBLE res = WaitForSingleObjectMsg(mutex, INFINITE);
if (res == WAIT_OBJECT_0)
{
 захвачен мютекс
} else
{
 пришло сообщение
}

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

Это сообщение отредактировал(а) Lazin - 13.12.2007, 09:01
PM MAIL Skype GTalk   Вверх
Nastya
Дата 13.12.2007, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 27.3.2002
Где: Мариуполь

Репутация: 3
Всего: 44



Вааще не поняла чем не нравится WaitFor... и зачем что-то еще изобретать.
Единственное что если при расчетах идет обращения к одним и тем же данным это аккуратно надо синхронизировать. 


--------------------
Что бы понять рекурсию, надо понять рекурсию

"Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор
PM MAIL   Вверх
Agentx86
Дата 13.12.2007, 12:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 110
Регистрация: 27.4.2006

Репутация: нет
Всего: нет



Если честно я тоже не мог понять препопада и хотябы один раз WaitForSingleObject вызвать надо это без вариантов. А идея какая. Название лабы "Синхронизация потоков", а я её сделал не используя объекты синхронизации. Вот он и начал "А вот я хочу убрать отсюда функцию WaitForMultiplyObject". Я ему говорю "А я поставлю 5 функций WaitForSingleObject". Препод ответчает "Мне так тоже неподойдет. Например первый поток будет работать дольше всего. Мы будет сначала ждать его, а пото только другие которые уже завершились. Потеря времени". Хотя вариант который предложили с критичискими секциями не будет быстрее чем 5 WaitForSingleObject. Он будет работать также. Потомучто мы в шесток потоке пытаемся сделать EnterCriticalSection сначала в первый поток, потом во второй............. .
Как решить эту задачу, чтобы она выполнялась по скорости как c WaitForMultiplyObject и не используя эту функцию я не знаю. Мне кажется препод сам не знает. Я у него на защите лабы поинтерисуюсь.

p.s. Nastya не употребляй слова паразиты. Кстати мы знакомы.

PM MAIL   Вверх
MAKCim
Дата 13.12.2007, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 1
Всего: 207



Agentx86, 
N потоков можно заменить на N - 1 поток
(поток, порождающий потоки, может заменить один из них)
это увеличит производительность

Добавлено через 5 минут и 16 секунд
Цитата(Agentx86 @  8.12.2007,  13:13 Найти цитируемый пост)
все потоки закончат вычисления просумировать все данные и чтото выполнить. 

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


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
baldina
Дата 14.12.2007, 00:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: нет
Всего: 101



Понятно. Препод хотел мьютексов, но не продумал ни задание, ни линию поведения  smile Бывает.
Имхо число WaitFor на скорость не влияет. В том смысле, что общее время работы в любом случае - время работы самого продолжительного потока. Вот если действительно начинать суммировать результаты уже завершенных потоков, как предложил  MAKCim - другое дело. 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0606 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.