Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: критическая секция, производительность  (Прочитано 39820 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 18-01-2011 07:43 » 

Вот такой вопрос:

пусть имеется контейнер, инкапсулированный в класс. Доступ к контейнеру производится через методы, в начале каждого метода локается критическая секция (так как предполагается многопоточное использование). Один поток обращается к контейнеру очень часто, второй - очень редко. Получается, что один поток часто впустую делает lock - может ли это сильно сказаться на производительности программы ?

Добавлено через 3 минуты и 21 секунду:
туплю, знаю же, что может. А что делать ?
« Последнее редактирование: 18-01-2011 07:47 от Алексей1153 » Записан

Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 18-01-2011 08:16 » 

Алексей1153++, а какие конкретно действия над контейнером выполняют оба потока?
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #2 : 18-01-2011 08:21 » 

Алексей1153++, проще проверить Улыбаюсь

я бы ничего не делал Улыбаюсь синхронизация при одном суперактивном потоке почти не вносит пинальти, проблемы ВОЗМОЖНО начнутся в куче активных потоков при куче ядер, на одном ядре вообще редко бывают проблемы
пока нет явной проблемы из-за синхронизации, не парься
если так сильно волнует, то сделай тест
с синхронизацией и без, поток писатель можно не поднимать
для тестов масштабируемости я использую вот это http://paralleluniverse.intel.com/
загружаешь туда бинарник и он запускается на разных железяках с разным числом ядер
на выходе получаешь, всякие графики и полезные статистики
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 18-01-2011 08:22 » 

Вад, периодические опросы состояний всех объектов (по таймеру), либо рандомный доступ (реакция на внешние раздражители). В принципе, циклы можно засунуть под критическую секцию, так ведь. То есть переселить их в методы контейнера. Главное, чтоб там быстро всё делаось. Вот тут может быть проблема (хотя, надо уточнить)

А насчёт внешних - надо посмотреть, в принципе, они не так уж часто бывают

Добавлено через 2 минуты и 39 секунд:
Антон (LogRus), ок, попробую. Но проверить непросто. Ладно, время покажет ) Просто раньше этот массив объектов был в одном потоке, да ещё статический. А теперь надо сделать разреженный массив + многопоточность
« Последнее редактирование: 18-01-2011 08:24 от Алексей1153 » Записан

Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 18-01-2011 09:03 » 

Алексей1153++, я имел в виду, изменяет ли каждый из потоков что-то в контейнере, и что именно. Чтоб понять, где именно требуется синхронизация для избегания гонок и прочих неприятностей.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 18-01-2011 09:49 » 

Вад, да, может и изменять. А потом будет изменять и количество объектов
Записан

resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 18-01-2011 20:55 » 

в общем-то критические секции "заявлены", как довольно быстрые объекты. Понятно что такие общие фразы мало о чём говорят, но конкретные "цифири" - кто же даст )) Да дело то даже не в этом. Главный момент - если синхронизировать надо, то что поделаешь. Какой смысл что-то замерять, если от синхронизации не уйти. Ты выбрал самый быстрый (из доступных в юзермоде) объект и твоя совесть может быть чиста, если конечно синхронизация вообще имеет смысл в твоём случае.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 18-01-2011 21:08 » 

да уж, синхронизировать всё равно придётся Улыбаюсь
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #8 : 25-01-2011 16:42 » 

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

С уважением Lapulya
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 31-01-2011 15:23 » 

Ну я бы не стал говорить, что тут чего-то огребаешь. Если секция занята, ждешь, когда освободится. В этом как раз и есть суть синхронизации. Совершенно нормально.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #10 : 31-01-2011 22:25 » 

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

« Последнее редактирование: 31-01-2011 22:33 от lapulya » Записан

С уважением Lapulya
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 31-01-2011 23:08 » 

lapulya,  переключений контекста в случае свободного события синхронизации не происходит.
накладные расходы - только на вызов API плюс проверка interlocked переменной.  ТОЛЬКО ЕСЛИ такая проверка провалена - тогда должно выполнится ожидание связанное с событием синхронизации этой секции (естественно с переключением контекста).
но если везде количество операций обернутых критической секцией сравнимы с этим кодом вызова API - тогда да, использовать критическую секцию просто обидно) или когда таких операций ооооочень много.

PS подробнее (правда с псевдокодом) http://www.rsdn.ru/article/baseserv/critsec.xml
« Последнее редактирование: 31-01-2011 23:10 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 01-02-2011 08:07 » 

lapulya, вот вроде бы всё понимаю, но логики не вижу. в общем-то любое ожидание (юзермодное) на объекте синхронизации сопровождается переключением контекста, что вполне логично. Ну и что? Если есть 2 и более потоков, полюбому когда-нибудь произойдёт переключение контекстов. Нормальная операция, и от неё полюбому никуда не деться. Я бы вообще не стал страдать по этому поводу.

 Относительно объектов синхронизации и Interlocked операций - понятно что одна инструкция намного быстрее, чем набор функций. Но сравнивать смысла нет, т.к. ситуации в которых они используются - разные. Если сделать самому эдакий объект синхронизации на основе interlocked-операций, то будет гораздо хуже, потому что контекст не будет переключаться сразу, как только выясниться что объект захвачен другим потоком. Получится полностью "счётный" поток, который будет использовать свой квант времени полностью (грузить проц и всё такое), но абсолютно бессмыслено, потому что пока работает этот поток, то другой никак не сможет "отпустить" объект синхронизации.

 Смысл в том, что ожидание на объекте синхронизации - это этап синхронизации. Ведь именно для того она и нужна, чтоб кто-то подождал кого-то. Поэтому я и говорю, что всё это нормально, и никаких "огрёбов" не вижу. А сравнивать скорость одной инструкции и целой функции...... ну я даже не знаю, и так всё ясно. Вот только одной инструкцией в данном случае никак не обойтись. Она неприменима.  Можно с таким же успехом говорить о том, что инкремент выполняется быстрее, чем сложение. Ну и что? Если нужно именно сложение то никуда не денешься.

 Ещё раз выведу основную мысль. Огребёшь и подождешь - не одно и тоже, потому что это ожидание сделано намеренно тем, кто в своём коде использует КС - в этом же суть синхронизации, и синхронизировать набор данных (а не одну переменную) по-другому не получится. Под "огребёшь" лично я понимаю, тормозной механизм, как сам по себе, так и по сравнению с чем-то, что может его полноценно заменить. Что есть быстрее чем КС (в юзермоде), и может полноценно её заменить?
« Последнее редактирование: 01-02-2011 08:12 от resource » Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 01-02-2011 10:30 » 

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

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

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
out-of-the-way
Новенький

ru
Offline Offline

« Ответ #14 : 01-02-2011 10:39 » 

А как зависит время необходимое для передачи объекта в критической секции от потока к потоку от количества потоков ожидающих входа в секцию? Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 01-02-2011 18:14 » 

out-of-the-way, расставь запятые! Ну и объект не передаётся, он защищается )
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #16 : 01-02-2011 19:51 » 

Ochkarik,
Цитата
lapulya,  переключений контекста в случае свободного события синхронизации не происходит.

я ж написал, что рассматривается занятый объект синхронизации (это я про "огребешь по полной").

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

А вот то что ты видимо не доконца понимаешь, что есть разные (по скорости работы) объекты синхронизации видно из твоего "подождать". Ochkarik описал (то, что я раньше написал ))) но может просто криво), в чем прелесть крит. секции, по сравнению с другими способами синхронизации потоков, явно использующими объекты ядра.
« Последнее редактирование: 01-02-2011 20:14 от lapulya » Записан

С уважением Lapulya
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 01-02-2011 20:08 » 

Это переключение контекста связано с тем, что поток впадает в ожидание. Конечно его переключат, он ведь ни чем не занят, чего "сидеть" просто так.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #18 : 01-02-2011 20:20 » 

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

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 01-02-2011 20:25 » 

lapulya, циклы я поместил в методы класса - локается перед циклом 1 раз. А где нельзя было в методы класса, я сделал перенумерацию с коллбэком - тоже один лок
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #20 : 01-02-2011 20:29 » 

ну тогда второй поток ждет пока цикл выполнится, хотя если это не критично (а наоборот выполнение цикра приоритетно), то так и надо делать
Записан

С уважением Lapulya
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 01-02-2011 20:48 » 

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

Тут вообще всё зависит от конкретной ситуации.
Если, допустим, один поток только пишет данные, а другой только читает, то имеет смысл добавить Событие в общую картину. Ведь читающему потоку нужно входить в КС, только тогда когда прибыли новые данные. А вот здесь уже самым главным будет правильно определить место из которого нужно сигналить событие.
А если, к примеру, данные читаются большими порциями, то можно вообще по-другому поступить. Выделить 2 больших буфера и привязать к каждому из них по событию.

Раз уж на то пошло, работа с большими потоками данных в реальном времени, это задача не для винды, а скорее для легковесной ОС реального времени. Когда дело этого касается, остается уповать только на комп помощнее. Сам с этим сталкивался.
« Последнее редактирование: 01-02-2011 20:50 от resource » Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 01-02-2011 20:52 » 

lapulya, про заход - да, пардон, проглядел то что вы выше писали. а про все остальное - ничего не понял)
по большому счету, все объекты синхронизации usermode так или иначе основываются на переключении контекста в случае ожидания. вообще то, для этого они и предназначены.  о чем спор - я правда не понимаю.

Алексей1153++, кстати, часто - это сколько?) время выполнения такого цикла - сколько в мс? сколько ресурсов ПК это все жрет?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 01-02-2011 21:00 » 

Ochkarik, ну я вот попытаюсь выразиться ещё более конкретно. "Средняя" часть 21 поста, это ключевой момент. Гланое это алгоритм, а какой конкретно применять объект синхронизации это вообще мелочи жизни (в юзермоде по крайней мере), и заострять на этом внимание вообще не стоит, так же как и на переключениях контекста.

ЗЫ можно хоть мьютекс, хоть семафор заюзать, если очень хочется Улыбаюсь это ничего не поменяет кардинальным образом в плане производительности
Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 01-02-2011 21:23 » 

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

PS
рихтер:
Цитата
Первое, что делает EnterCriticalSection, — исследует значения элементов структу ры CRITICAL_SECTION. Если ресурс занят, в них содержатся сведения о том, какой поток пользуется ресурсом. EnterCriticalSection выполняет следующие действия.

Если ресурс свободен, EnterCriticalSection модифицирует элементы структуры, указывая, что вызывающий поток занимает ресурс, после чего немедленно возвращает управление, и поток продолжает свою работу (получив доступ к ресурсу).
Если значения элементов структуры свидетельствуют, что ресурс уже захвачен вызывающим потоком, EnterCriticalSection обновляет их, отмечая тем самым, сколько раз подряд этот поток захватил ресурс, и немедленно возвращает уп равление. Такая ситуация бывает нечасто — лишь тогда, когда поток два раза подряд вызывает EnterCriticalSection без промежуточного вызова LeaweCritical Section.
Если значения элементов структуры указывают на то, что ресурс занял другим потоком, EnterCriticalSection переводит вызывающий поток в режим ожидания. Это потрясающее свойство критических секций: поток, пребывая в ожидании, не тратит ни кванта процессорного времени Система запоминает, что данный поток хочет получить доступ к ресурсу, и - как-только поток, занимавший этот ресурс, вызывает LeaveCriticalSection — вновь начинает выделять нашему пото ку процессорное время При этом она передает ему ресурс, автоматически обновляя элементы структуры CRITICAL_SECTION

и нашел новый вариант для себя InitalizeCriticalSectionAndSpinCount() (начиная с w2k)
Цитата
Критические секции и спин-блокировка

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

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

Для использования спин-блокировки в критической секции нужно инициализи ровать счетчик циклов, вызвав:

BOOL InitalizeCriticalSectionAndSpinCount( PCRITICAL_SECTION pcs, DWORD dwSpinCount);

Как и в InitializeCriticalSection, первый параметр этой функции — адрес структуры критической секции. Но во втором параметре, dwSpinCount, передается число циклов спин-блокировки при попытках получить доступ к ресурсу до перевода потока в состояние ожидания. Этот параметр может принимать значения от 0 до 0x00FFFFFF. Учтите, что на однопроцессорной машине значение параметра dwSpinCount игнори руется и считается равным 0. Дело в том, что применение спин-блокировки в такой системе бессмысленно: поток, владеющий ресурсом, не сможет освободить его, пока другой поток «крутится» в циклах спин-блокировки.

Вы можете изменить счетчик циклов спин-блокировки вызовом:

DWORD SetCriticalSectionSpinCount( PCRITICAL_SECTION pcs, DWORD dwSpinCount);

И в этой функции значение dwSpinCount на однопроцессорной машине игнорируется.

Па мой взгляд, используя критические секции, Вы должны всегда применять спин блокировку — терять Вам просто нечего, Moгут возникнуть трудности в подборе зна чения dwSpinCount, по здесь нужно просто поэкспериментировать. Имейте в виду, что для критической секции, стоящей па страже динамической кучи Вашего процесса, этот счетчик равен 4000.

PPS о как, с висты еще и забавная функция Slim Reader/Writer (SRW) Locks появилась) правда описание скромное очень...
« Последнее редактирование: 01-02-2011 22:18 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 01-02-2011 21:53 » 

Алексей1153++ хочет, чтобы у него один поток работал на полной скорости, а другой изредка читал данные. И Алексей1153++ придумал использовать критическую секцию, а теперь сомневается, хорошо ли это. Нехорошо!

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

Цитата: resource
lapulya, вот вроде бы всё понимаю, но логики не вижу. в общем-то любое ожидание (юзермодное) на объекте синхронизации сопровождается переключением контекста, что вполне логично. Ну и что? Если есть 2 и более потоков, полюбому когда-нибудь произойдёт переключение контекстов. Нормальная операция, и от неё полюбому никуда не деться. Я бы вообще не стал страдать по этому поводу.
Совершенно верно. Не знаю, зачем тут lapulya мутит воду, но скорость работы объекта синхронизации в данной ситуации не имеет значения, поскольку первый поток рано или поздно будет остановлен на время работы второго при любом способе синхронизации.

Как я уже где-то писал, есть проблема и есть видение её решения. Алексей1153++ вместо того, чтобы сосредоточиться на проблеме, занимает наше внимание своим видением её решения. Поэтому предлагаю вернуться к проблеме.


Проблема: первый поток в идеале должен работать непрерывно. Как позволить второму потоку читать данные?

Решение 1: общий объект (в который первый поток пишет, и из которого второй поток читает данные) становится объектом синхронизации. Такое решение даёт перерывы в работе первого потока - проблема не решена. Зачем этому посвящать 23 поста споров??

Решение 2: если данных немного, первый поток может сам скопировать их в pipe и послать сигнал второму потоку "данные готовы", после чего спокойно продолжать работать. Второй поток по своему усмотрению реагирует на сигнал и на поступившие данные. Если второму потоку данные нужны редко, то у решения есть недостаток: второй поток всё же вынужден будет реагировать на все сигналы и чистить pipe от накопившихся там данных - делать ненужную для себя работу. Тем не менее, первый поток никогда не уходит в ожидание, и его дополнительные затраты времени связаны лишь с копированием результатов в pipe и посылкой сигнала.

Первый поток удалять/перезаписывать эти данные не может по той причине, что если он это будет делать - в этот момент второй поток как раз может их читать, и данные испортятся. Т.е. если вместо очереди использовать volatile-переменную - придётся делать критическую секцию доступа к ней, что эквивалентно решению 1 и проблему не решает. Это так называемое решение, зависящее от состояний. Решение с pipe - это решение, не зависящее от состояний (stateless), что активно используется в функциональном программировании.

Решение 2.1: Решение 2 можно улучшить, если ввести вспомогательный интерфейсный третий поток (в одной старой книжке по Ada называвшийся "задача-курьер"), который можно останавливать на критических секциях. Тогда потоки 1 и 3 будут взаимодействовать согласно решению 2 - через pipe и сигналы, поток 3 будет выполнять черновую работу по очистке pipe от данных и готовить их для потока 2, но не будет обязан немедленно чистить pipe. Потоки 2 и 3 будут взаимодействовать согласно решению 1 - через критическую секцию и дожидаться завершения работы друг друга.

Решения 3, 4, 5... включайте фантазию и не перестаньте думать, что параллельное программирование сводится к объектам синхронизации.
« Последнее редактирование: 01-02-2011 21:55 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 01-02-2011 21:58 » 

ой, ну пайп это уже как-то...
а фантазию включать можно только когда задача известна) иначе вариантов слишком много
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #27 : 02-02-2011 01:51 » 

я так понял что без синхронизации обойтись было нельзя - это раз
текущая реализация - внутри цикла юзать крит. секцию - два

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

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

вроде все четко...

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

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

PPS
Не любит меня Димка )))))
« Последнее редактирование: 02-02-2011 02:06 от lapulya » Записан

С уважением Lapulya
out-of-the-way
Новенький

ru
Offline Offline

« Ответ #28 : 02-02-2011 06:04 » 

out-of-the-way, расставь запятые! Ну и объект не передаётся, он защищается )

А как зависит время, необходимое для передачи объекта в критической секции от потока к потоку, от количества потоков ожидающих входа в секцию? Улыбаюсь
Имеется ввиду промежуток времени между выходом одного потока из критической секции, и входом другого.

P.S. rsdn куда то пропал.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #29 : 02-02-2011 06:49 » 

Решение 2.2: Небезызвестная двойная буферизация в модифицированном виде - улучшение идеи с pipe, которое позволит убрать вспомогательный третий поток. Заводится двойной буфер данных, которые второй поток должен читать, а первый - формировать. В начале буфер пуст. Запускается первый поток и начинает работать с одной частью буфера - в неё он записывает и перезаписывает по мере необходимости свои данные, может вообще её использовать как угодно для своих нужд. Запускается второй поток и через какое-то время хочет читать данные. Он посылает сигнал первому потоку: "хочу читать данные" (это можно сделать так: завести в первом потоке bool-переменную, сброшенную в false, а второй поток её может переключить в true; второй поток заводит ManualResetEvent "данные готовы", который после после посылки сигнала "хочу читать" сброшен, и второй поток сам себя на нём останавливает в ожидании). Первый поток в своём цикле когда-нибудь проверит, что флаг "хочу читать" установлен, тогда он заканчивает работу с первой частью буфера, оставляя там нужные данные, сам переключается на работу с другой частью буфера, сбрасывает флаг "хочу читать" в false, и посылает сигнал второму потоку "данные готовы" (устанавливает вышеупоминавшийся ManualResetEvent). Второй поток, ожидающий сигнала, просыпается и читает данные из первой части буфера - эта операция безопасна, поскольку первый поток их больше не трогает, работая со второй частью буфера.

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

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


P.S. Тема ни про Windows, ни про C/C++, а про архитектуру - можно в раздел "Технологии разработки..."
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines