Просмотр полной версии : Крит секции.
Господа кто как ищет в программе взаимо-блокировки которые могут возникнуть при использовании крит секций. Есть для этого какие то специальные методы?
Например у меня в программе есть несколько потоков которые одновременно могут взаимодействуют с несколькими объектами. В каждый объекте есть свои крит секции.
Я заметил что блокировка может как правило возникнуть в следующей ситуации:
Первый поток обращается к первому объекту и использует его крит секцию.
Одновременно второй поток обращается ко второму обхекту с его крит.секц.
Первый поток пытается обратится ко второму обхекту не выходя из крит секции первого. И соответвенно ждет пока из этой к.с. выйдет второй поток.
Второй поток пытается обратится к первому объекту не выходя из к.с. второго. И соответственно все зависает на веки вечные.
Для упрощения работы с крит секциями в каждом обхекте я создал по 2 функции EnterCS и LeaveCS.
Если бы иметь возможность внутри этих функций мониторить состояние крит секций других моих объектов я мог бы хотя бы определить где и что привело к блокировке.
В нт системах есть tryentercriticalsection в ряде случаев позволяющаяя избежать дедлоков. В идеале постарайся сделать синхронизацию по иерархии чтоб секции порядком выше не вызывались кодом низшего порядка. Если незнаеш где дедлок можеш юзать мутекс - таже секция но можно задать время ожидания и если оно вышло вывести месагу отладочную.
Добавлено через 3 минуты
Зы трайэнтер это посути и есть попытка войти в секцию но проверив ее состояние и если занята не пытатса ее ждать. Как она обернута в делфи хз я vcl не юзаю.
SyncObjs.TCriticalSection.TryEnter не покатит?
з.ы. я нуп на делфях не писал
Да есть функция tryentercriticalsection ноне совсем пойму логику ее использования. Выполняя эту функцию я могу сразу знать захвачена эта крит секция другим потоком или нет, если да то какие мои действия, мне ведь все равно нужно в нее войти когда она освободится?
На ум приходит только зацикливать с каким то интервалом tryentercriticalsection пока она не захватит успешно объект крит. секции или пока не истечет какое то время.
логика в том что бы дождаться освобождения крит секции, да наверное надо лупится пока занято, но это точно исключит дедлоки...
А так Тряй вам поможет с:
"Если бы иметь возможность внутри этих функций мониторить состояние крит секций других моих объектов я мог бы хотя бы определить где и что привело к блокировке." ))
etoken, в смысле в коде моего входа в крит секцию пытаться войти в крит секции других объектов для проверки занятости, например:
bool MyInterCritSect()
{
if (TryEnterCriticalSection(cs2))//проверяем не занята ли крит секция второго объекта
{//если нет
LeaveCriticalSection(cs2);
EnterCriticalSection()cs1);
return true;
}
else
{//если да
ShowMessage("Возможно блокирование ищите ошибку в логике программы:)");
return(false);
}
}
"Лупится" - это загрузит систему, если вызывать Sleep() то затормозит программу
Вот что по этому поводу пишет некий Oraizer
"Я считаю TryEnterCriticalSection() вообще бесполезной. Идеология критических секций такова, что они призваны защищать инварианты структур данных в пределах одного приложения в предположении, что нарушения инвариантов кратковременны, а значит коллизии случаются редко. Критические секции в отличие от мьютексов очень легки, приложение может их использовать сотнями, тысячами и больше, не особо нагружая систему. Отсюда и некоторые их ограничения, в частности отсутствие таймаутов, невозможность комбинировать их с другими объектами синхронизации и неопределённость поведения системы при несоблюдении правил обращения с ними. В таких исходных условиях TryEnterCriticalSection() может быть полезна в единственном случае - попробовать захватить и отказаться выполнять запрошенное действие в случае неудачи. Ни разу не припомню, чтобы мне понадобился такой сценарий. Всё остальное от лукавого, критические секции в других условиях эксплуатации просто вряд ли вообще подходят.
Средством защиты от deadlocks является отладка. Их просто не должно быть. Обходные пути в лице нарушенных инвариантов - это ещё большее зло."
Источник (http://forum.sources.ru/index.php?showtopic=327727&st=15)
Добавлено через 5 минут
А так Тряй вам поможет с:
"Если бы иметь возможность внутри этих функций мониторить состояние крит секций других моих объектов я мог бы хотя бы определить где и что привело к блокировке." ))
Как мне поможет Try? Изменить глобальное время ожидания входа в крит секцию в системе InitializeCriticalSectionAndSpinCount() и при исключении долгого ожидания искать ошибки в программе?
Как мне поможет Try? Изменить глобальное время ожидания входа в крит секцию в системе InitializeCriticalSectionAndSpinCount() и при исключении долгого ожидания искать ошибки в программе?
по крайне мере позволит понять в какой момент беда в логике синхронизации. Я имею ввиду использование так как вы описали в примере выше, тупо чекать состояние второй крит. секции, а там уже пытаться "понятть и простить".
etoken, в смысле в коде моего входа в крит секцию пытаться войти в крит секции других объектов для проверки занятости, например:
bool MyInterCritSect()
{
if (TryEnterCriticalSection(cs2))//проверяем не занята ли крит секция второго объекта
{//если нет
LeaveCriticalSection(cs2);
EnterCriticalSection()cs1);
return true;
}
else
{//если да
ShowMessage("Возможно блокирование ищите ошибку в логике программы:)");
return(false);
}
}
"Лупится" - это загрузит систему, если вызывать Sleep() то затормозит программу
Вот что по этому поводу пишет некий Oraizer
"Я считаю TryEnterCriticalSection() вообще бесполезной. Идеология критических секций такова, что они призваны защищать инварианты структур данных в пределах одного приложения в предположении, что нарушения инвариантов кратковременны, а значит коллизии случаются редко. Критические секции в отличие от мьютексов очень легки, приложение может их использовать сотнями, тысячами и больше, не особо нагружая систему. Отсюда и некоторые их ограничения, в частности отсутствие таймаутов, невозможность комбинировать их с другими объектами синхронизации и неопределённость поведения системы при несоблюдении правил обращения с ними. В таких исходных условиях TryEnterCriticalSection() может быть полезна в единственном случае - попробовать захватить и отказаться выполнять запрошенное действие в случае неудачи. Ни разу не припомню, чтобы мне понадобился такой сценарий. Всё остальное от лукавого, критические секции в других условиях эксплуатации просто вряд ли вообще подходят.
Средством защиты от deadlocks является отладка. Их просто не должно быть. Обходные пути в лице нарушенных инвариантов - это ещё большее зло."
Источник (http://forum.sources.ru/index.php?showtopic=327727&st=15)
Добавлено через 5 минут
Как мне поможет Try? Изменить глобальное время ожидания входа в крит секцию в системе InitializeCriticalSectionAndSpinCount() и при исключении долгого ожидания искать ошибки в программе?
все прально написал чувак, трайэнтер скорее поможет диагностировать наличие дедлока нежели будет иметь практическое применение.
как я сказал выше постарайся сделать иерархию какуюто и попробуй избежать лишних "секций в секциях".
я трайэнтер не юзал, юзал мутекс с ожиданием скажем в 10 сек - если за это время не удавалось его захватить выводилась мессага о взаимоблокировке в таком-то месте
alexteam
22.08.2011, 20:12
Если бы иметь возможность внутри этих функций мониторить состояние крит секций других моих объектов я мог бы хотя бы определить где и что привело к блокировке.
eurekalog. поможет если дезлочиться основной поток приложения.
хм, чего не писал ещё ни разу не возникало необходимости использовать критические секции внутри критической секции, в связи с чем ни о каких взаимных блокировках и думать не приходиться)
имхо любую задачу можно реализовать без вложенных критических секций...
Да это в трейд боте там такого я понакручивал. В основном проблеммы бывают с основым потоком при заполнение визуальных компонентов. Случаются ситуация когда необходимо одновременно захватить крит секции двух разных объектов. Я конечно стараюсь обходить такие ситуации использую промежуточные переменные но это неудобно и бывает допускаю ошибки которые потом тяжело найти.
Зачем в трейдере такие расколбасы?
У меня синхронизируетса 3 нити:
1)поток клиента: рисование интерфейса, ввод клавы/мышки, прочие хуки.
2)Контрольный поток : обслуживает радар, разбирает и диспетчирует очередь пакетов проги, отслеживает состояние ядра программы, при необходимости формирует события для 3го потока.
3)рабочий поток: в нем крутитса скрипт и обрабатываютса события передаваемые скрипту
в итоге даже самым стремным скриптом сложно вывести программу из строя. На край этот поток завершитса с ошибкой или может быть "убит" и запущен заново.
дедлоков нет тока благодаря миниальной вложености блокировок и соблюдения "иерархии"
У меня в 1 приложении запускается сразу n+ окон которые могут взаимодейтсвовать друг с другом.
Для каждого окна следующие потоки:
1. Поток приема и разбора пакетов. Он сам практически ничего не делает. Принял пакет, обработал, обновил соответствующие данные и ушел ждать следующего пакета.
2. Поток скрипта. В обычном режиме он спит и просыпается обычно по указанию из потока приема пакета или главного потока для выполнения какой топ оследовательности действий, например если барыгу убили то полдняотся и вернуться на точку, сесть на продажу.
3. Поток автобоя. В обычном режиме спит и может быть запущен по команде и потока скрипта. Это мне нужно для прокачки барыг, когда делаю нубские квесты.
4. Поток выполнения коротких действий. Например взять пати, сесть на трейд, отправить письмо, пробежать посмотреть цены в выделенной зоне. Может быть запущен из любого потока включая главный, на каждое окно может ыть одновременно запущено несколько таких потоков. Обычно этот поток отрабатывает свою задачу и уничтожается.
Ну и главный поток приложения в котором при необходимости перерисовывается интерфейс, выводится карта, рассчитывается положение движущихся объектов на карте в данный момент времени.
3 и 4 разумнее в одно обьединить. Смысла создавать 5 вообще не вижу никакова смысла.
В 6 проблем быть недолжно - зашол в секцию -> считал данные -> обновил данные -> запер секцию. Обычно этот поток никто не ждет и дедлок исключен. Ему просто кидаетса евент или месага что пора обновитса.
Понублю: А чем крит секция принципиально отличается от мутексов ?
Смысл один. У мутанта больше возможностей.
1 м может быть глобальной и доступной в других процессах. Секция тока в своем.
2 м можно захватить одним потоком неск.раз (ессно чтоб освободить нада стокаже раз вызвать release) секция же скорее всего "сломаетса" при двух ентерах или ливах.
понятно что цена за это скорость, мутекс требует обращения к ядру ос а это пассивный irq level
GoodDrone
24.08.2011, 15:57
2 м можно захватить одним потоком неск.раз (ессно чтоб освободить нада стокаже раз вызвать release) секция же скорее всего "сломаетса" при двух ентерах или ливах.
да вы, батенька, фантазёр:
After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection or TryEnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns. The thread enters the critical section each time EnterCriticalSection and TryEnterCriticalSection succeed. A thread must call LeaveCriticalSection once for each time that it entered the critical section.
3 и 4 разумнее в одно обьединить.
Тогда тяжело будет реализовать всякие плюшки в бою. Такие как смена локаций когда заканчиватются нужные мобы, подсчет квестовых предметов, реакция на появление игроков в радиусе видимости.
Нет конечно это все можно сделать в потоке боя с помощью кучи настраевамых параметров, но тут теряется шибкость. Текст скрипта я могу проверять на перезапуская программу и на ходу настраивать пошагово.
да вы, батенька, фантазёр:
ну.. я написал "скорее всего". непроверял ибо не допускал таково :)
смысл в том что у нее нет счетчика блокировок.
GoodDrone
24.08.2011, 18:01
смысл в том что у нее нет счетчика блокировок.
Есть таймаут, правда глобальный.
Есть таймаут, правда глобальный.
впервые слышу что у секции есть таймаут.
у мутекса есть задаваемый вручную от 0 до INFINITE
mira, у TryEnterCriticalSection можно задать таймаут, после которого если так и не удалось войти в секцию, то TryEnterCriticalSection завершается возвращая соответствующий код результата. Собсно даже не можно а нужно, и так же от 0 до INFINITE
GoodDrone
24.08.2011, 19:21
mira, у TryEnterCriticalSection можно задать таймаут...
Где?
впервые слышу что у секции есть таймаут.
Я нашел только глобальный:
The timeout interval is specified by the following registry value: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Contro l\Session Manager\CriticalSectionTimeout.
GoodDrone, хм, да, чтот я гоню, нет у них таймаута при TryEnterCriticalSection, с чем то его перепутал видать
трайэнтер мы причислили к извращениям вроде :)
поэтому InitializeCriticalSectionAndSpinCount не считаетса
Ссама переменная крит секции имеет несколько полей, что они означают? Может быть для поиска конфликтов можно их проверять?
Вот как объявлена эта запись в Delphi:
_RTL_CRITICAL_SECTION = record
DebugInfo: PRTLCriticalSectionDebug;
LockCount: Longint;
RecursionCount: Longint;
OwningThread: THandle;
LockSemaphore: THandle;
Reserved: DWORD;
end;
Ссама переменная крит секции имеет несколько полей, что они означают? Может быть для поиска конфликтов можно их проверять?
Вот как объявлена эта запись в Delphi:
_RTL_CRITICAL_SECTION = record
DebugInfo: PRTLCriticalSectionDebug;
LockCount: Longint;
RecursionCount: Longint;
OwningThread: THandle;
LockSemaphore: THandle;
Reserved: DWORD;
end;
ненадо там ниче проверять. опиратса на эти поля крайне не рекомендуетса (как и на саму структуру). кроме как большего гемора не получиш.
LockCount - это типа счетчик запираний (у секции поидеи 0 или 1)
OwningThread - ид потока вошедшего в секцию
LockSemaphore - помоему для случая какраз с трайэнтером (иначе не используетса)
LockCount - это типа счетчик запираний (у секции поидеи 0 или 1)
а мне кажется это для счётчика потоков ожидающих входа в секцию
Добавлено через 7 минут
а хотя...
The most important fields of the critical section structure are as follows:
In Microsoft Windows 2000, and Windows XP, the LockCount field indicates the number of times that any thread has called the EnterCriticalSection routine for this critical section, minus one. This field starts at -1 for an unlocked critical section. Each call of EnterCriticalSection increments this value; each call of LeaveCriticalSection decrements it. For example, if LockCount is 5, this critical section is locked, one thread has acquired it, and five additional threads are waiting for this lock.
The RecursionCount field indicates the number of times that the owning thread has called EnterCriticalSection for this critical section.
The EntryCount field indicates the number of times that a thread other than the owning thread has called EnterCriticalSection for this critical section.
When the first thread calls the EnterCriticalSection routine, the critical section's LockCount, RecursionCount, EntryCount and ContentionCount fields are all incremented by one, and OwningThread becomes the thread ID of the caller. EntryCount and ContentionCount are never decremented.
At this point, four different things can happen.
The owning thread calls EnterCriticalSection again. This will increment LockCount and RecursionCount. EntryCount is not incremented.
A different thread calls EnterCriticalSection. This will increment LockCount and EntryCount. RecursionCount is not incremented.
The owning thread calls LeaveCriticalSection. This will decrement LockCount (to -1) and RecursionCount (to 0), and will reset OwningThread to 0.
Another thread calls LeaveCriticalSection. This produces the same results as the owning thread calling LeaveCriticalSection -- it will decrement LockCount (to -1) and RecursionCount (to 0), and will reset OwningThread to 0.
When any thread calls LeaveCriticalSection, Windows decrements LockCount and RecursionCount. This feature has both good and bad aspects. It allows a device driver to enter a critical section on one thread and leave the critical section on another thread. However, it also makes it possible to accidentally call LeaveCriticalSection on the wrong thread, or to call LeaveCriticalSection too many times and cause LockCount to reach values lower than -1. This corrupts the critical section and causes all threads to wait indefinitely on the critical section.
Да вот только как читать эти данные из рекорда крит секции. Вдруг они в этот момент обновляются.
Да вот только как читать эти данные из рекорда крит секции. Вдруг они в этот момент обновляются.
завернуть еще в 1 крит секцию :p :D
а вообще ты слишком злопотребляеш многопоточкой, поток стоит создавать тогда когда есть острая необходимость. тут я ее невижу совсем :)
Да у меня еще их немного. В клиенте L2 около 100 потоков.
Yegor, не иди по стопам корейцев)
Да у меня еще их немного. В клиенте L2 около 100 потоков.
чем щитал :) ?
Если открыть список хендлов процесса их там совнем немного.
supernewbie
25.08.2011, 18:37
через оли было около 50 точно
чем щитал :) ?
Если открыть список хендлов процесса их там совнем немного.
В диспетчере задач посмотрел. ProcessExplorer столько же показывает. Это касается только саркиофа. На фришках гораздо меньше, причем с каждым апдейтом фроста и хроник потоков все больше и больше.
В диспетчере задач посмотрел. ProcessExplorer столько же показывает. Это касается только саркиофа. На фришках гораздо меньше, причем с каждым апдейтом фроста и хроник потоков все больше и больше.
а ну у нас фришка. там то понятно туча сторожевых потоков. они к игре отношение имеют весьма косвенное и синхронизация примитивная
туча сторожевых потоковвот только какой смысл больше чем в двух сторожевых потоках хоть убей не пойму...
вот только какой смысл больше чем в двух сторожевых потоках хоть убей не пойму...
взаимоконтроль однака
ну и задачки разные выполняют видимо отчасти.
вон както вирус поймал. создал 2 процесса - один убил другой сразуже перепрятал его экзешник и переименовал и запустил снова. убил этот - прикрыл тот.
mira, ну дык для взаимоконтроля 3х потоков за глаза хватит...
а задачек там особых быть не должно для кучи потоков
в общем что то там в Ереване странное делают)
vBulletin® v3.6.11, Copyright ©2000-2024, Jelsoft Enterprises Ltd. Перевод: zCarot