|
Обновите ArcaOS до уровня NeoWPS
- Установите набор PNG иконок, нарисованных дизайнером, специализирующемся на оформлении OS/2
- Установите eSchemes 2018, чтобы менять цвета и кнопки на рабочем столе
|
Использование семафоров в среде Presentation Manager |
TITLE: Использование семафоров в среде Presentation Manager
DATE: 2010-05-23 21:10:45
AUTHOR: Dmitry A. Steklenev
Что такое мьютекс
Мьютекс (англ. mutex, от mutual exclusion - взаимное исключение) - одноместный
семафор, служащий в программировании для синхронизации одновременно
выполняющихся потоков. Приложения обычно используют мьютексы для защиты общих
ресурсов от одновременного доступа из разных потоков или процессов.
Мьютексы являются гораздо более быстрым решением по сравнению с другими
способами синхронизации доступа к общим ресурсам. Так, поток переводится в
состоянии ожидания только в том случае, если мьютекс уже захвачен другим
потоком. Это является главным преимуществом мьютексов перед критическими
секциями. Т.к. при выполнении последних, в состояние ожидания переводятся
все другие потоки текущего процесса, даже если в данный момент времени им
вовсе и не нужен доступ к общему ресурсу. Также отсутствует необходимость ждать
завершения выполнения предыдущего запроса, который опять же может быть и не
связан с доступом к общему ресурсу, как это происходит в случае использования
для синхронизации каких либо очередей.
Взаимная блокировка
Основная опасность при использовании нескольких мьютексов, это возникновение
взаимных блокировок. При возникновении такой блокировки, два потока могут
бесконечно ожидать нужный им ресурс. Пользователь при этом имеет одну, а то и
более, зависших программ. Простейший пример взаимной блокировки:
- Поток 1 успешно захватывает мьютекс A.
- Поток 2 успешно захватывает мьютекс B.
- Поток 1 ожидает захвата мьютекса B.
- Поток 2 ожидает захвата мьютекса A.
Выявление взаимных блокировок при отладке программ является непростой задачей,
так как для их возникновения нужны специфические условия одновременного
выполнения нескольких потоков. Простейшим способом избежания взаимной
блокировки является разработка иерархии мьютексов и захват и освобождение их
в одном, строго определенном, порядке. Существует еще ряд приемов борьбы со
взаимными блокировками, но их изучение не является целью данной статьи.
Следует отметить, что в OS/2 реализована разновидность мьютексов, уменьшающая
вероятность возникновения взаимной блокировки: поток может повторно захватить
мьютекс, ранее уже захваченный этим же потоком.
Мьютексы в среде Presentation Manager
Используя мьютексы в среде PM, с большой вероятностью, вы столкнетесь с
ситуациями, очень напоминающими взаимную блокировку. Это может происходить даже
в том случае, если на все приложение использован один единственный мьютекс.
Почему же такое происходит? Для этого сначала необходимо разобраться с
механизмом пересылки сообщений между потоками в Presentation Manager.
WinPostMsg и WinSendMsg
В случае с WinPostMsg cообщение кладётся в очередь потока, которому принадлежит
окно, являющееся адресатом для данного сообщения. После этого, выполнение
потока, пославшего сообщение, продолжается. Отправителю неизвестно, когда
посланное сообщение будет обработано и каковы будут результаты этой обработки.
Чтобы как-то разделить посылку сообщения с помощью WinPostMsg от аналогичного
действия, выполненного с помощью WinSendMsg, будем называть последнее действие
передачей сообщения. Разница между ними примерно такая же, как между
посылкой письма по почте и личной передачей его из рук в руки.
В случае передачи сообщения, выполнение передающего потока останавливается до
тех пор, пока сообщение не будет обработано получателем. После обработки
сообщения, результат обработки возвращается передающему потоку и его выполнение
возобновляется. Следует отметить, что если окно, являющееся адресатом для
сообщения, принадлежит тому же самому передающему потоку, то будет произведен
прямой вызов функции обработки сообщений для этого окна. В случае же, если окно
находится в другом потоке и этот поток в текущий момент занят обработкой
другого сообщения (руки у получателя уже заняты), передающий поток будет
ожидать до тех пор, пока эта обработка не завершится. И только после этого
произойдет передача сообщения получателю.
Что же происходит
Если внимательно прочитать предыдущий абзац, то будет очевидно, что WinSendMsg
ведет себя точно так же, как ведут себя мьютексы в OS/2. Возможно, что
механизм передачи сообщения в Presentation Manager и реализован с помощью
мьютексов. А раз у нас появился дополнительный, нигде не учтенный мьютекс, то
могут появиться и неучтенные взаимные блокировки. Простейший пример:
- Поток 1 успешно захватывает мьютекс A.
- Поток 2 ожидает захвата мьютекса A.
- Поток 1 ожидает возможности передачи сообщения в Поток 2.
Как же избежать проблем с мьютексами
Напрашивается простой вывод, что использовать мьютексы в среде PM не стоит. Или
нужно очень внимательно следить за тем, чтобы между захватом и освобождением
мьютекса не вызывались никакие функции, могущие вызвать передачу сообщений в
другие потоки. И то и другое весьма усложняет процесс разработки приложений.
Однако, решение существует. И существует давно. Но почему то, ему уделяется
крайне мало внимания. Найти упоминания о нём крайне трудно. Итак, внимание,
этим решением является использование функции WinRequestMutexSem.
Отличием этой функции от всем известной DosRequestMutexSem является то, что
поток, вставший в ожидание мьютекса с помощью этой функции, может продолжать
принимать сообщения, передаваемые другими потоками. Нужно отметить, что
принимаются и обрабатываются только сообщения, переданные WinSendMsg.
Сообщения, посылаемые WinPostMsg, по прежнему помещаются в очередь сообщений и
ожидают своей обработки.
У этой функции есть два недостатка:
- Время ожидания, указанное при вызове функции, может не соблюдаться с
достаточной точностью. Происходит это потому, что между попытками захватить
мьютекс, происходит обработка других сообщений, и время этой обработки
может быть различным.
- Порядок следования сообщений может частично нарушаться. Т.е. если при
обработке сообщения A, поток встал в ожидание мьютекса, то сообщение B,
передача которого началась позже, в итоге будет обработано раньше A.
Оба этих недостатка не являются достаточно существенными, чтобы отказаться от
преимуществ, которые дает использование WinRequestMutexSem.
Рекомендации
Если разрабатывается приложение или библиотека, предназначенные для работы в
среде Presentation Manager,
то для захвата семафоров необходимо использовать только
вызовы WinRequestMutexSem. Даже в том случае, если на текущий момент
использование DosRequestMutexSem является вполне безопасным. Это позволит
избежать возможных проблем при дальнейшей модернизации кода. Не следует бояться
дополнительных накладных расходов, так как при вызове WinRequestMutexSem из
потока, который не имеет очереди сообщений и, следовательно, не может быть
получателем сообщений, вызов WinRequestMutexSem будет автоматически
преобразован в вызов DosRequestMutexSem.
Необходимо отметить, что Presentation Manager также предоставляет функции
WinWaitEventSem и WinWaitMuxWaitSem, являющиеся аналогами функций
DosWaitEventSem и DosWaitMuxWaitSem и обладающими теми же замечательными
свойствами, что и WinRequestMutexSem.
Попробуй программу:
|
T&V HappyPlayer - управление телеприемниками Brooktree 848/878
|
Комментарии: Алексей 2010-05-25 13:44:05 | Это все интересно, но лично для меня трудно понимаемо. Так как я ни когда с этим не работал. Хотелось бы более полную информацию: что этот такое вообще, где применяются (лучше с примерами), в каких языках, как получить доступ. И неплохо бы ссылочки где можно еще глянуть информацию по теме. Я вот в оси использую активно реккс, мне это нужно? И если да, то как получить к этому доступ. | dixie 2010-05-25 15:15:23 | Ээ, ну бездумно лепить WinRequestMutexSem тож не стоит ;) Как бы, если мутекс зачем-то поставили, значит он не зря стоит и SendMsg вполне может сломать логику. | GlassMan 2010-05-26 17:23:55 | Ну не знаю. Проблема в том, что мьютекс то как раз обычно ставят вовсе не для того, чтобы останавливать очередь сообщений. А неожиданно получают дидлок. | Sergey Posokhov 2010-06-07 20:41:16 | "Решение существует. И существует давно." - и называется оно "DosCallNPipe()" :)
А решение с помощью "WinRequestMutexSem()" - не решение, а "костыль". Всё равно post-сообщения до потока не доходят... | Eugene Gorbunoff 2010-06-12 12:59:41 | From: Lars Erdmann
It would be helpful to have this article available in english :-)
source: [url] | ElectroDog 2010-10-19 13:25:00 | Вечная проблема OS/2 сообщества. Вместо того чтобы намотать на ус и спокойно использовать или не использовать, каждый предлагает свое "гениальное" решение. Основываясь на опыте разработки своего грандиозного "PM приложения" из 15-и строк... |
Прокомментируйте эту статью (напоминаем, автор работал над текстом несколько недель, уважайте мнение других).
|
|
Готовая eComStation на SSD диске
Последний активный опрос: Какая высота барьера RPM?
[Google]
|
IBM OS/2 Warp
|