|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Янв 21, 2004 21:01:06 Привет всем! Я первый раз задаю вопрос на этом форуме, поэтому прошу простить меня, если что не так… У меня возник вопрос, касающийся критических секций в многопоточных приложениях. Дело в том, что я всегда считал, что критическая секция – это фрагмент программы, защищенный от одновременного выполнения несколькими потоками. Критическую секцию в данный момент может выполнять только один поток. Тут мне все понятно. Недавно я скачал из интернета курс лекций: ‘Программирование для Windows: введение в интерфейс Win API’. Автор курса: Архипова Елена Николаевна, старший преподаватель кафедры КТС, ВГУЭС. В нем, понятие ‘критическая секция’ определено так: раздел кода, во время выполнения которого поток не может быть прерван. Может быть, кто ни будь из Вас, объяснит мне, что это значит? Ведь если допустить, что это действительно так, то получается что, любой взятый поток, войдя в критическую секцию, может захватить себе все процессорное время на неопределенный срок. IMHO, такого не может быть! Я хочу услышать Ваши мнения по данному вопросу, а то я уже не знаю, что и думать… Заранее, спасибо за Ваши ответы. |
|
|
Дата: Янв 21, 2004 21:47:01 Мне это напоминает игру словами... http://www.rsdn.ru/article/baseserv/critsec.xml?print 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. Я полагаю, что, действительно, поток не может быть прерван. Другим потоком! Но не самой ОС. Скедьюлер вполне может прервать такой поток. Почему бы и нет? |
|
|
Дата: Янв 22, 2004 15:52:41 volodya Точно. Но 1. Поток может быть прерван, и ПОТОК тут не причём. 2. Потоки тут вообще не причём ******************************************************* Критическая секция -- это объект синхронизации, который позволяет правильно организовать МОНОПОЛЬНЫЙ доступ к некоторому РЕСУРСУ. ******************************************************* На Асме, Критическая секция реализуется обычно одной командой ;; al == 0
xchg al,флаг
;; |
|
|
Дата: Янв 22, 2004 17:57:00 <small offtop> не хочу никого обидеть, но реальный случай: Газета Дальпресс (Владивосток), объявление (года 3-4 назад) "Требуется программист со знанием.... (точно не помню)...С дипломом ВГУЭС просьба не обращаться. Вот и думай потом чего они там за курсы составляют... Одно у них хорошо, за те деньги которые они с богатеньких студентов дерут, вычислительные центры нормально оборудованы. и CISCO 4 штуки разных было чтоб на лабах ковырять, не в пример "нашему" политену...(ДВГТУ т.е.) </small offtop> |
|
|
Дата: Янв 23, 2004 18:36:58 [продолжу оффтоп] Недавно видел подобное объявление, но для юристов. Не в почёте нынче ВГУЭС... [/оффтоп] |
|
|
Дата: Янв 23, 2004 20:39:02 Edmond "На Асме, Критическая секция реализуется обычно одной командой xchg al,флаг" а где проверка-то? на то - можно входить потоку в критическую секцию, или нет? я лично использую cmpxchg. |
|
|
Дата: Янв 23, 2004 22:42:09 volodya Спасибо Вам за ссылку! Интересно было почитать... >Я полагаю, что, действительно, поток не может быть прерван. Другим потоком! Но не самой ОС. Скедьюлер вполне может прервать такой поток. Почему бы и нет? 1. Я не совсем понял, что вы имеете в виду, когда говорите о прерывании потока другим потоком. Произведя несколько экспериментов, я получил следующие результаты: a) Несколько потоков продолжают выполняться параллельно даже если один из них вошел в критическую секцию. Исключение тут представляет тот случай, когда другие потоки хотят войти в уже занятую критическую секцию. В этом случае они приостанавливаются и ожидают ее освобождения, после чего получают к ней доступ в порядке очередности (и/или приоритетов?); b) Поток A может прервать поток B (TerminateThread), даже в том случае, если поток B, в это время, выполняет код в критической секции. В принципе, по моему, так и должно быть. А, в общем: в этом вопросе я согласен с возражениями Edmond'а. 2. Что такое: 'Скедьюлер'? Это, случайно, не 'планировщик'? Я новичок в этом деле... Edmond Я согласен с Вашими возражениями! Edmond Grenader Действительно, Вы показали интересный способ организации критической секции! Но тут возникает несколько вопросов по его дальнейшей реализации: 1. Допустим, критическая секция занята, на момент обращения к ней потока. Каким образом организовать ожидание ее освобождения? Если делать это в цикле, то получится не эффективно, т.к. поток будет, при этом, использовать ресурсы процессорного времени, в то время как при стандартной организации поток просто усыпляется...; 2. Допустим, на момент освобождения критической секции, ее ожидает несколько потоков, имеющих разные приоритеты. Как правильно 'разрулить' такую ситуацию? При стандартной организации, этим занимается планировщик... 3. В свете вышесказанного, возникает главный вопрос: насколько эффективно применение этого способа по сравнению со стандартным подходом? DaemoniacaL >Вот и думай потом чего они там за курсы составляют... Ну, ошибки, опечатки и всякие недоразумения можно встретить в практически любой книге... Например, я приобрел себе недавно книгу 'Ассемблер для Windows', автор: Владислав Пирогов. Так вот, в ней утверждается, что функция CreateThread возвращает хэндл потока в переменной, указатель на которую передается ей в последнем параметре... И на этом утверждении построено дальнейшее объяснение… На самом деле, в этой переменной возвращается ID потока, а его хэндл, эта функция, передает в своем возвращаемом значении. Это только один пример из множества... А что касается обсуждаемого здесь курса лекций, то он мне в общем нравится! Прикольное оформление (хотя и оляпистое), показывает, что человек создававший его подошел к этому делу с душой... IMHO, плохую репутацию учреждения нельзя, огульно, переносить на всех его сотрудников. В конце концов, плохая репутация может объясняться тем, что там большой процент выпускников, не имея достаточных знаний, покупает диплом… Судя по всему, на то и похоже, если верить Вашему утверждению о том, что там учатся ‘богатенькие' студенты… |
|
|
Дата: Янв 24, 2004 00:03:02 Oleg_SK Edmond, видимо, имел в виду не критическую секцию, а что-о сроднее InterlockedExchange (из разряда - пустить только один поток, а остальные - в обход). А критическую секцию одной строчкой на асме понятное дело, не написать. Возможно, я не совсем корректно это высказал - исправляюсь... |
|
|
Дата: Янв 24, 2004 00:13:11 Grenader Понятно... С кем не бывает? |
|
|
Дата: Янв 24, 2004 01:06:44 volodya Мне понравилось то, что я нашел, прогулявшись по Вашей ссылке! Если можно, дайте мне еще ссылки на столь же подробную и исчерпывающую документацию по следующим темам: 1. Семафоры; 2. События; 3. Взаимоисключения; 4. Pipe (применяемые для обмена информацией между процессами); 5. Почтовые ящики (применяемые для обмена информацией между процессами); 6. Файлы, отображаемые в память (У меня, по этой теме, почти нет серьезной и исчерпывающей информации. Во всех моих доках эта тема затрагивается крайне поверхностно...); 7. Управление памятью (кучи). Заранее благодарен Вам. P.S.: Не ругайтесь сильно! Я бы и сам, наверно, нашел эту инфу, но не могу из-за крайне ограниченного времени для Internet’а. |
|
|
Дата: Янв 24, 2004 20:13:29 Oleg_SK Меня на "ты". Вежливый молодой человек :) Исключение тут представляет тот случай, когда другие потоки хотят войти в уже занятую критическую секцию. Это не исключение. Это то, ради чего каша и заварилась. Объекты синхронизации! Что до планировщика. Я же сказал - приблизительно. Точный алгоритм работы планировщика винды в деталях мне неизвестен. Только общие принципы. Скажем, если истечет квант времени, отпущенный данному потоку, он, скорее всего, будет прерван осью. В случае твоих критических секций цепочка выглядит так: EnterCriticalSection -> ntdll!RtlEnterCriticalSection -> ZwWaitForSingleObject А дальше - копай ядро ;) |
|
|
Дата: Янв 24, 2004 20:14:46 Да, RSDN ответит на многие твои вопросы по этим темам. Для всего остального - найди себе Джеффери Рихтера "Windows для профессионалов". Там есть ответы на все твои вопросы. Купи эту книгу. |
|
|
Дата: Янв 26, 2004 14:56:11 · Поправил: Edmond "На Асме, Критическая секция реализуется обычно одной командой xchg al,флаг" а где проверка-то? на то - можно входить потоку в критическую секцию, или нет? я лично использую cmpxchg. Ну неужели домыслить дальше так тяжело?? :))) Да, команда есть такая, но она то поддерживается с какого пня? Не менее как с P6 (мне так кажется...) Действительно, Вы показали интересный способ организации критической секции! Это не интересный способ -- а единственный для тех, кто пишет на асм. Я бы сказал -- естественный способ. Все объекты ядра, созданные для синхронизации в Win32 всегда можно эффективно реализовывать как комбинации команд монопольного чтения / записи + объект событие. Кстати в *nix есть только сигналы!!! 1. Допустим, критическая секция занята, на момент обращения к ней потока. Каким образом организовать ожидание ее освобождения? Если делать это в цикле, то получится не эффективно, т.к. поток будет, при этом, использовать ресурсы процессорного времени, в то время как при стандартной организации поток просто усыпляется...; ОК. Хотя это уже переходит в статью.. тем не мене. Давайте рассмотрим самый простой метод монопольного чтения/записи, который мне нравится называть поплавком -- xchg Итак. Пусть в памяти хранится переменная, которая - равна 0, если что-либо занято - равна TRUE -- если что- либо свободно Итак.
xor eax,eax
xchg eax,flag
;; Всё, значение флага теперь == 0. Ресурс захвачен.
;; Проверяем, а не был ли он захвачен до нас?
test eax,eax
jz goto_wait
;; НЕТ, он свободен. Используем
............................
goto_wait:
;; Он занят?
;; Тогда мы цепляемся к объекту ядра Windows, которое
;; будет освобождено как только ресурс освободится.
;; Этот объект может быть ЛЮБЫМ объектом ядра для
;; синхронизации.
2. Допустим, на момент освобождения критической секции, ее ожидает несколько потоков, имеющих разные приоритеты. Как правильно 'разрулить' такую ситуацию? При стандартной организации, этим занимается планировщик... Так он и так этим занимается. (Хотя я нередко ввожу свою систему приоритетов. Но это уже темы для статей) Идею я описал выше. 3. В свете вышесказанного, возникает главный вопрос: насколько эффективно применение этого способа по сравнению со стандартным подходом? Как минимум в 1000 тактов лучше. Потому что если объект свободен, ты не вызываешь функции ядра Win32. |
|
|
Дата: Янв 26, 2004 16:04:19 · Поправил: Edmond Edmond, видимо, имел в виду не критическую секцию, а что-о сроднее InterlockedExchange (из разряда - пустить только один поток, а остальные - в обход). А критическую секцию одной строчкой на асме понятное дело, не написать. Возможно, я не совсем корректно это высказал - исправляюсь... И правильно поняли, и не правильно. Критическая секция может быть написана при помощи связки xadd/xchg + Win32 Event Эта реализация будет намного более эффективней, чем обычно. Тем более. Вот например как может быть реализован семафор. Но более продвинутый. -= Абстракт =- К ОДНОМУ ресурсу рвутся несколько потоков. Если ресурс захватывают более N потоков, то остальные блокируются, то есть ждут пока не освободятся текущие. Теперь мы тоже делаем переменную в памяти. Но теперь мы будем в ней хранить число потоков, которые могут свободно подключиться к ресурсу одновременно. Тогда при помощи команды xadd попытка захватить ресурс выглядит так
;; Правило игры такое:
;; Если значение переменной в памяти = -1
;; то никто не имеет права менять его значения
xor eax,eax
dec eax
xchg eax,var
cmp eax,0
;; Если значение равно 0,
;; Значит слишком много желающих захватить ресурс
;; Если eax < 0, то кто-то читает var,
;; и ничего делать всё равно нельзя.
;; Нам приходится стать в ожидание.
.......................................................
.......................................................
;; Иначе пользуемся ресурсом.
;; Обратите внимание на один интересный факт.
;; Изменение ячейки происходит так.
;; var равна -1
;; А в eax == содержалось текущее значение
;; После этой команды ячейка будет свободна для модификации
dec eax
xchg eax,var
Восстановление счётчика происходит похожим образом.
xor eax,eax
dec eax
xchg eax,var
inc eax
jz wait
;; Мда. ничего не поделаешь. но придётся подождать
;; пока кто-то модифицирует ячейку.
............................
;; Иначе
;; Теперь var = var + 1
;; Ресурс свободен...
xchg eax,var
Особенностью данного алгоритма является ситуация при которой поток, который хочет освободить ресурс не может освободить его, потому что другие пытаются захватить. Однако в РЕАЛЬНОСТИ такая ситуация может возникнуть очень редко (потому что контексты переключаются с частотой намного большей чем время выполнения 2-х команд), поэтому данный алгорим эффективен. Обратите внимание. Данные алгоритм построен таким образом, что значение var никогда не будет меньше 0. (-1 -- это служебное значение) |
|
|
Дата: Янв 26, 2004 16:18:42 Edmond Было интересно почитать, спасибо. У тебя просто талант популяризатора - как у Перельмана :) дугое дело, что я много интересно узнал из листингов мелкософтских функций - вот она, ирония судьбы... |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.146 |