Ожидание сообщений и объектов
Функция MsgWaitForMultipleObjects аналогична функции WaitForMultipleObjects. Применяйте ее для того, чтобы разрешить потоку или процессу обработку событий пользовательского интерфейса, таких как щелчки мышью, во время ожидания перехода объектов синхронизации в сигнальное состояние.
Дополнительные рекомендации относительно использования мьютексов и объектов CRITICAL_SECTION
К этому времени мы успели познакомиться со всеми объектами синхронизации Windows и исследовали их применимость на ряде примеров. Мьютексы и объекты CS рассматривались первыми, а поскольку события мы еще будем интенсивно использовать в следующей главе, то настоящую главу целесообразно завершить рекомендациями относительно применения мьютексов и объектов CS для обеспечения корректности выполнения, удобства сопровождения и повышения производительности программ.
Приведенные ниже утверждения сформулированы, как правило, в терминах мьютексов, однако, если не оговорено иное, все сказанное относится и к объектам CS.
• Если функция WaitForSingleObject, одним из аргументов которой является дескриптор мьютекса, вызывается без использования конечного интервала ожидания, то вызывающий поток может оказаться блокированным на неопределенное время. Ответственность за то, чтобы захваченный (блокированный) мьютекс в конечном счете был освобожден (разблокирован), возлагается на программиста.
• Если поток завершает выполнение или его выполнение прерывается до того, как он покинет (разблокирует) объект CS, то этот объект остается блокированным. Чрезвычайно полезным свойством мьютексов является то, что владеющий ими поток может завершить выполнение, не уступив прав владения мьютексом.
• Не пытайтесь получить доступ к ресурсам, защищаемым мьютексом, если функция WaitForSingleObject вызвана с использованием конечного интервала ожидания.
• Ожидать перехода блокированного мьютекса в сигнальное состояние могут сразу несколько потоков. Когда мьютекс освобождается, то только один из ожидающих потоков получает права владения мьютексом и переводится в состояние готовности планировщиком ОС на основании действующей стратегии приоритетов и планирования. Не следует делать никаких предположений относительно того, что какой-либо поток будет пользоваться приоритетом; как и в любом другом случае, программу следует проектировать таким образом, чтобы приложение работало корректно независимо от того, какой именно из ожидающих потоков получит права владения мьютексом и возобновит выполнение. Те же замечания остаются справедливыми и в отношении потоков, ожидающих наступления события; никогда не следует предполагать, что при переходе объекта события в сигнальное состояние освободится какой-то определенный поток или что потоки будут разблокированы в какой-то определенной очередности.
• К критическому участку кода относятся все операторы, расположенные между точками программы, в которых поток приобретает права владения мьютексом и уступает их. Для определения нескольких критических участков кода может быть использован один и тот же мьютекс. Корректная организация программы предполагает, что критический участок кода, определяемый мьютексом, в каждый момент времени может выполняться только одним потоком.
• Определяемая мьютексами степень детализации программы, или гранулярность мьютексов (mutex granularity), оказывает влияние на производительность и требует серьезного рассмотрения. Размер каждого критического участка кода ни в коем случае не должен превышать необходимой величины, и мьютекс не должен захватываться на более длительный промежуток времени, чем это необходимо. Использование критических участков кода чрезмерно большого размера, захватываемых на длительные промежутки времени, снижает параллелизм и может оказывать отрицательное влияние на производительность.