Разработка многопоточных приложений. Рудалев В.Г - 12 стр.

UptoLike

12
4. Синхронизация потоков
Как уже упоминалось , при доступе потоков к общим ресурсам (глобаль-
ным данным, одному и тому же файлу, DLL, коммуникационному порту и т. п .)
возникают коллизии. Предотвратить коллизии можно с помощью различных
средств синхронизации. Чаще всего для этой цели используются : критические
секции, исключающие семафоры (мьютексы ), обычные семафоры, события. Все
упомянутые механизмы основаны на блокировке доступа к ресурсу , пока этот ре-
сурс занят каким - либо потоком .
Рассмотрим более подробно механизм критической секции, ограничив -
шись его реализацией на базе функций API Win32 (как обычно, в Delphi имеются
аналогичные классы - надстройки). Участок кода, содержащий потенциально
опасные обращения к ресурсу , помечается как «критическая секция» . Перед вхо-
дом в критическую секцию проверяется глобальная запись типа TRTLCriticalSec-
tion (структуру записи см . в файле ..\borland\delphi4\source\rtl\win\windows.pas), в
которой отмечено, выполняется ли критическая секция в данный момент времени
каким - либо другим потоком. Если секция не занята, поток допускается к работе.
В начале критической секции необходимо вызвать подпрограмму API
procedure EnterCriticalSection (sect:TRTLCriticalSection);
которая проверяет состояние записи sect: TRTLCriticalSection и, если в за-
писи секция помечена как занятая другим потоком, приостанавливает текущий
поток, пока критическая секция не освободится .
В конце критической секции вызывается подпрограмма
procedure LeaveCriticalSection (sect:TRTLCriticalSection);
которая делает пометку в записи , что критическая секция свободна, и дру -
гой поток в соответствии с приоритетом получает квант времени и входит в кри-
тическую секцию .
Предварительно перед использованием необходимо проинициализировать
запись sect: TRTLCriticalSection с помощью процедуры
procedure InitializeCriticalSection(Sect);
а при завершении использования удалить :
procedure DeleteCriticalSection(Sect1);
В рассматриваемом ниже примере первая операция выполняется в обра-
ботчике события создания формы OnCreate, а вторая в обработчике события
удаления формы из памяти OnDestroy.
       4. С ин хро н изация п о то ко в

         К ак уж е уп оминалось, п ри доступ е п отоков к об щ им ресурсам (г лоб аль-
ны м данны м, одному итому ж е ф айлу, DLL, коммуникационному п орту ит.п .)
возникаю т коллизии. П редотвратить коллизии мож но с п омощ ью различны х
средств синхронизации. Ч ащ е вс         ег о для этой цели ис п ользую тся: кр и т и чески е
секци и , и склю ча ю щи е сем а ф ор ы (м ью т ексы), обычн ые сем а ф ор ы, событ и я. В се
уп омянуты емеханизмы основаны наб локировкедоступ ак ресурсу, п окаэтотре-
сурсзаняткаким-либ о п отоком.
         Рассмотрим б олее п одроб но механизм критической секции, ог раничив-
ш ись ег о реализацией наб азеф ункций API Win32 (как об ы чно, в Delphi имею тся
аналог ичны е классы -надстройки). У часток кода, содерж ащ ий п отенциально
оп асны е об ращ ения к ресурсу, п омечается как « критическая с        екция». П еред вхо-
дом в критическую с      екцию п роверяется г лоб альная зап ись тип аTRTLCriticalSec-
tion (структуру зап исисм. в ф айле ..\borland\delphi4\source\rtl\win\windows.pas), в
которой отмечено, вы п олняется ликритическая секция в данны й моментвремени
каким-либ о друг им п отоком. Е слисекция незанята, п оток доп ускается к раб оте.
         В началекритической секциинеоб ходимо вы звать п одп рог рамму API

       procedure EnterCriticalSection (sect:TRTLCriticalSection);

        которая п роверяетсостояниезап исиsect: TRTLCriticalSection и, еслив за-
п исисекция п омеченакак занятая друг им п отоком, п риостанавливаеттекущ ий
п оток, п окакритическая секция неосвоб одится.
      В концекритичес   кой секциивы зы вается п одп рог рамма

       procedure LeaveCriticalSection (sect:TRTLCriticalSection);

         которая делаетп ометку в зап иси, что критическая секция своб одна, идру-
г ой п оток в соответствиисп риоритетом п олучаетквантвремениивходитв кри-
тическую секцию .
         П редварительно п еред исп ользованием необ ходимо п роинициализировать
зап ись sect: TRTLCriticalSection сп омощ ью п роцедуры

       procedure InitializeCriticalSection(Sect);

       ап ризаверш енииисп ользования – удалить:

       procedure DeleteCriticalSection(Sect1);

       В рассматриваемом ниж еп римереп ервая оп ерация вы п олняется в об ра-
б отчикесоб ы тия создания ф ормы OnCreate, авторая – в об раб отчикесоб ы тия
удаления ф ормы изп амятиOnDestroy.


12