ма динамически повышать уровень потоков с малым приорите-
том, давая им шанс на выполнение. Впрочем, надеяться на Win-
dows — гиблое дело; лучше не трогать приоритеты, пока не бу-
дет в этом необходимости. Теперь давайте поговорим про син-
хронизацию.
Синхронизация потоков
Как вы уже поняли, организация программного комплекса,
состоящего из нескольких процессов или потоков, неминуемо
приводит к необходимости синхронизации выполняемых фраг-
ментов программы. Синхронизация может иметь разные аспек-
ты: поток может получать сообщение о завершении фрагмен-
та другого потока, ему может быть запрещено обращаться к
некоторым данным, пока с ними работает другой поток, также
могут накладываться ограничения на количество потоков, ко-
торые используют одни и те же данные. Синхронизация про-
цессов и потоков осуществляется с помощью различных объек-
тов Windows, к которым относятся как сами потоки и процес-
сы, так и программные средства: критические секции, семафо-
ры, мьютексы, события. Для объектов, служащих для синхрони-
зации, в системе предусмотрено два состояния —
свободное
(signaled)
и
занятое (nonsignaled).
Занятое состояние объекта
используется для запрета тех или иных действий, а свободное —
для разрешения.
Анализ состояния осуществляется с помощью двух функций
синхронизации —
W a i t F o r S i n g l e O b j e c t {H A N D L E h O b j e c t , DW O R D
d w T i m e o u t
) и
W a i t F o r M u l t i p l e O b j e c t (D W O R D c O b j e c t s , H A N -
D L E * l p h O b j e c t s , B O O L f W a i t A l l , D W O R D d w T i m e o u t )
. В функ-
ции
W a i t F o r M u l t i p l e O b j e c t
( ) первый параметр означает чис-
ло синхронизирующих объектов, второй — адрес массива деск-
рипторов объектов, третий — флаг ожидания
(t r u e и л и f a l s e ),
четвертый — лимит времени ожидания в миллисекундах. Если вы
хотите, чтобы функция ожидала событие в течение неограничен-
ного времени, то в качестве последнего параметра следует ука-
зать константу
i n f i n i t e
.
Усыпление потока
— это очень эффек-
тивная операция. Когда поток спит, он не потребляет системных
ресурсов. Вы также можете усыпить поток функцией
s i e e p O .
А
теперь приступим к подробному рассмотрению объектов.
Итак, критические секции.
Критической секцией
нозывается
фрагмент программы, который должен обладать монопольным
доступом к некоторым данным любого содержания и объема. Их
особенность в том, что, в отличие от остальных объектов син-
хронизации, они годятся только для потоков. Чтобы использовать
критические секции в программе, следует определить глобаль-
ную переменную типа
c r i t i c a l _ s e c t i o n
.
Эта переменноя ни-
как не связана с потоками и общими данными. О на лишь опре-
деляет, можно ли в данный момент предоставить доступ к общим
данным тому или иному потоку. В первичном потоке следует вы-
полнить инициализацию критической секции, вызвав функцию
i n i t i a l i z e C r i t i c a l S e c t i o n (
). Фрагменты функций потоков,
в которых осуществляется обращение к общим данным, следует
защищать функциональными скобками
E n t e r C r i t i c a l S e c t i o n f
)
. . . L e a v e C r i t i c a l s e c t o i n O .
Механизм критических секций
очень прост. Например, работают два потока: в первом проис-
ходит операция и чтение/запись в общие данные, а второй лишь
пытается работать с ними. Как только второй поток вызовет функ-
цию
E n t e r C r i t i c a l S e c t i o n O ,
он остановится и будет ждать,
пока первый не закончит работу с данными, вызвав функцию
L e a v e C r i t i c a l S e c t o i n ( ) .
С критическими секциями разобрались, теперь переходим к
мьютексам.
Они очень похожи на критиче-
ские секции. Для применения мьютексов сле-
дует объявить глобальную переменную ти-
па
H A N D L E , В
которую будет
П О М е Щ в Н Д в С К -
риптор мьютекса. Конечно, нам надо ини-
циализировать дескриптор мьютекса, что мы
и делаем, вызывая функцию
c r e a t e M u t e x ( ) ,
котороя имеет прототип
H A N D L E c r é â t e M u t e x (
L P S E C U R I T Y _ A T T R I B U T E S l p M u t e x A t t r i b -
utes, // адрес структуры с атрибутами
защиты
B O O L b l n i t i a l O w n e r , / /
флаг началь-
ного владения, определяет исходный
режим владения — если он равен
T R U E ,
право владения мьютексом принадлежит породившему его
потоку
L P C T S T R lp N a m e / /
имя мьютекса
);
Надо отметить, что программа, в которой реализованы мью-
тексы, работает на порядок медленнее, чем программа с крити-
ческими секциями. Это обусловлено тем, что на выполнение функ-
ций
E n t e r C r i t i c a l S e c t i o n (
) и
L e a v e C r i t i c a l s e c t o i n O
ухо-
дит девять машинных команд, в то время как организация мью-
тексов и использование функций
W a i t F o r S i n g l e o b j e c t O
и
W a i t F o r M u l t i p l e O b j e c t
() требуют 600 команд. Поэтому не
стоит использовать мьютексы там, где можно обойтись без них.
Настало время
событий.
Это эффективный, но не самый лег-
кий способ синхронизации. С помощью этого объекта поток уве-
домляет другой поток об окончании каких-либо действий (напри-
мер, подготовки данных для печати). Событие перед использова-
нием надо создать, что мы и сделаем, использовав функцию с ге -
a t e E v e n t
(). О на имеет следующий прототип:
H A N D L E C r e a t e E v e n t (
L P S E C U R I T Y _ A T T R I B U T E S I p E v e n t A t t r i b u t e s , / /
адрес ат-
рибутов защиты
B O O L b M a n u a l R e s e t ,
// флаг ручного сброса события
B O O L b l n i t i a l s t a t e , / /
флаг начального состояния собы-
тия
L P C T S T R lp N a m e / /
имя события
);
События могут быть двух видов: со
сбросом вручную
и с
ав-
тосбросом.
События со сбросом вручную требуют явной уста-
новки состояния с помощью функции
S e t E v e n t
(), События с
автосбросом сбрасывают свое состояние, как только в управ-
ляемом потоке функция ожидания события обнаружит, что оно
установлено, и, соответственно, разбудит поток. События с ав-
тосбросом удобно использовать в циклических фрагментах про-
граммы. Создать событие со сбросом вручную можно, задав в
качестве значения параметра
b l n i t i a l s t a t e
константу
T R U E
(для события с автосбросом —
f a l s e ).
Существует функция
P u l s e E v e n t O ,
которая устанавливает в качестве параметра
событие в свободное состояние и, после того как все ожидаю-
щие потоки проснулись, тут же снова сбрасывает его, предот-
вращая повторное выполнение защищенных участков потоков,
пока это событие не будет явно установлено в управляющем
потоке.
Теперь давайте коротко про
семафоры.
В отличие от других
объектов синхронизации, семафоры имеют еще и
счетчик ресурн
са.
Семофор считается
сброшенным,
если значение счетчика
равно нулю.
Функции ожидания,
примененные к семафору, не
сбрасывают его в занятое состояние, а лишь уменьшают на еди-
ницу значение его счетчика. Следовательно, к семафору можно
несколько раз применять функцию ожидания. Для семафоров от-
ведена функция
R e l e a s e S e m a p h o r e
(), которая увеличивает на
единицу значение счетчика. Для создания семафора служит функ-
ция
C r e a t e S e m a p h o r e
(). О на имеет четыре параметра. Первый
и последний аналогичны функции
C r e a t e E v e n t
(), а второй и
третий — эта ночальное и максимальное значение счетчика, со-
ответственно. Семафоры удобно использовать в тех случаях, ко-
гда в программе имеется ограниченное количество экземпляров
определенного ресурсо. Создав в них семафор с начальным зна-
чением счетчика, равным числу имеющихся экземпляров ресур-
са, мы можем обеспечить одновременное использование любо-
го их количества — от одного до максимума.
Т Г г л е р е д п А а т и и л и
МОИ
К О М П Ь Ю Т ЕР
Щ
.
М О И К О М П Ь Ю Т Е Р
Г
предыдущая страница 41 Мой Компьютер 2004 41 читать онлайн следующая страница 43 Мой Компьютер 2004 41 читать онлайн Домой Выключить/включить текст