Критична секція (англ. critical section) — об'єкт синхронізації потоків у Windows, що дозволяє запобігти одночасному виконанню деякого критичного набору операцій (зазвичай пов'язаних з доступом до даних) кількома потоками.
Загально
Об'єкт критичної секції представляє ділянку сирцевого коду, яка в кожен окремий момент може виконуватися лише одним потоком. Критичні секції можна створювати і знищувати, але вони не мають дескрипторів, тому не можуть використовуватись різними процесами. У той же час, для синхронізації потоків одного процесу критичні секції – один з найшвидших і найпростіших способів. Об'єкти критичних секцій не є об'єктами ядра, а розміщуються у користувацькому адресному просторі процесу.
В більшості реалізацій з кожною критичною секцією пов'язано лічильник, і захоплення критичної секції можливе лише за нульового значення цього лічильника. Захоплення означає атомарну зміну лічильника на 1. Щоразу, коли потік, що володіє критичною секцією, знов входить до неї, лічильник збільшується на 1, при виході — зменшується. Перехід до чекання на події ядра здійснюється лише у випадку, якщо значення змінної лічильника до спроби захоплення було вже більше 1, тобто критична секція зайнята і є реальне «змагання» двох або більше потоків за ресурс критичної секції.
Порівняння критичних секцій та м'ютексів
Критична секція значною мірою виконує ті ж завдання, що і м'ютекс.
У операційних системах Microsoft Windows головна відмінність між м'ютексом і критичною секцією в тому, що м'ютекс є об'єктом ядра і може бути використаний кількома процесами одночасно, критична секція ж належить процесу і служить для синхронізації тільки його потоків. Процедура входу і виходу критичних секцій зазвичай займає менший час, ніж аналогічні операції м'ютекса.
Між м'ютексом і критичною секцією є й термінологічні відмінності. Процедура, аналогічна захопленню м'ютекса, називається входом у критичну секцію, зняття блокування м'ютекса — виходом з критичної секції.
Робота з критичними секціями у Windows
Для роботи з критичними секціями використовують Windows API.
Перед використання критичної секції її слід ініціалізувати за допомогою процедури InitializeCriticalSection. Її опис мовою :
void WINAPI InitializeCriticalSection( __out LPCRITICAL_SECTION lpCriticalSection );
Опис мовою Delphi:
procedure InitializeCriticalSection( var lpCriticalSection: TRTLCriticalSection );
Перед входом у код критичної секції потік має викликати функцію EnterCriticalSection. Її опис мовою :
void WINAPI EnterCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );
Якщо в цей момент жоден з потоків процесу не володіє критичною секцією, то вона стає власником її об'єкта і продовжує виконання. Якщо секція вже захоплена іншим потоком, викликаючий потік зупиняється до її звільнення. Потік, який володіє критичною секцією, може повторно викликати EnterCriticalSection без блокування свого виконання.
Відразу після закінчення роботи зі спільним ресурсом потік повинен звільнити об'єкт критичної секції викликом процедури LeaveCriticalSection. Її опис мовою :
void WINAPI LeaveCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );
Опис мовою Delphi:
procedure LeaveCriticalSection( var lpCriticalSection: TRTLCriticalSection );
Вона звільняє об’єкт критичної секції, і якщо в цей час існують інші потоки, які очікують її звільнення, одна з них стає новим власником і продовжує виконання. Якщо потік завершиться, не звільнивши критичної секції, вона переходить у невизначений стан і робота програми може бути заблокована.
Для кожної критичної секції система підтримує лічильник входжень, тому потік повинна звільнити її стільки разів, скільки захоплювала. Недотримання цієї умови приведе до блокування потоку ("зависання").
Слід також пам'ятати, що спроба виходу з критичної секції, якою потік не володіє, також приведе до блокування викликаючого потоку.
Програма може здійснити спробу захоплення об'єкта критичної секції без зупинки потоку. Для цього використовують функцію TryEnterCriticalSection (опис мовою ):
BOOL WINAPI TryEnterCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );
Опис функції на Delphi:
function TryEnterCriticalSection( var lpCriticalSection: TRTLCriticalSection ): BOOL;
У момент виклику вона перевіряє, чи критична секція захоплена якимось іншим потоком. Якщо так — функція повертає false, у протилежному випадку вона захоплює критичну секцію та повертає true.
Після завершення роботи з критичною секцією вона повинна бути вивільнена викликом процедури DeleteCriticalSection. Опис на :
void WINAPI DeleteCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );
Опис на Delphi:
procedure DeleteCriticalSection( var lpCriticalSection: TRTLCriticalSection );
Приклад використання критичної секції
Нижче приведено фрагмент коду (мовою Delphi), який забезпечує синхронізацію роботи потоку при звертанні до спільної (для кількох потоків) змінної A. Задля усунення неоднозначності, викликаної конкуренцією потоків, подібний фрагмент програми повинен бути у всіх потоках, які працюють зі змінною A. Якщо подібної синхронізації не використовувати, то виникатиме конкуренція потоків.
// Оголошення критичної секції var ICriSec : TRTLCriticalSection; ................................... // Ініціалізація - до запуску першого потоку InitializeCriticalSection(ICriSec); ................................... // Функція потоку function ThreadFunc(Ptr: Pointer): LongInt; var I : integer; begin for I := 1 to 1000000 do begin // Якийсь код EnterCriticalSection(ICriSec); Inc(A); LeaveCriticalSection(ICriSec); // Якийсь код end; end; .................................... // Знищення об'єкта критичної секції DeleteCriticalSection(ICriSec);
Примітки
- Коноваленко І.В., Федорів П.С. Системне програмування у Windows з прикладами на Delphi, Т:ТНТУ.- 2012 [ 8 грудня 2012 у Wayback Machine.].
- . Архів оригіналу за 20 квітня 2012. Процитовано 29 квітня 2012.
- . Архів оригіналу за 18 квітня 2012. Процитовано 29 квітня 2012.
- . Архів оригіналу за 30 січня 2012. Процитовано 29 квітня 2012.
- . Архів оригіналу за 20 квітня 2012. Процитовано 29 квітня 2012.
- . Архів оригіналу за 22 квітня 2012. Процитовано 29 квітня 2012.
Див. також
- Багатонитевість
- потік
- Синхронізація процесів
- М'ютекс
- Семафор (програмування)
- Ф'ютекс, швидкий користувацький м'ютекс
- Подія (Windows)
Ця стаття потребує додаткових для поліпшення її . (січень 2016) |
Це незавершена стаття про програмування. Ви можете проєкту, виправивши або дописавши її. |
Це незавершена стаття про операційні системи. Ви можете проєкту, виправивши або дописавши її. |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Kritichna sekciya angl critical section ob yekt sinhronizaciyi potokiv u Windows sho dozvolyaye zapobigti odnochasnomu vikonannyu deyakogo kritichnogo naboru operacij zazvichaj pov yazanih z dostupom do danih kilkoma potokami ZagalnoOb yekt kritichnoyi sekciyi predstavlyaye dilyanku sircevogo kodu yaka v kozhen okremij moment mozhe vikonuvatisya lishe odnim potokom Kritichni sekciyi mozhna stvoryuvati i znishuvati ale voni ne mayut deskriptoriv tomu ne mozhut vikoristovuvatis riznimi procesami U toj zhe chas dlya sinhronizaciyi potokiv odnogo procesu kritichni sekciyi odin z najshvidshih i najprostishih sposobiv Ob yekti kritichnih sekcij ne ye ob yektami yadra a rozmishuyutsya u koristuvackomu adresnomu prostori procesu V bilshosti realizacij z kozhnoyu kritichnoyu sekciyeyu pov yazano lichilnik i zahoplennya kritichnoyi sekciyi mozhlive lishe za nulovogo znachennya cogo lichilnika Zahoplennya oznachaye atomarnu zminu lichilnika na 1 Shorazu koli potik sho volodiye kritichnoyu sekciyeyu znov vhodit do neyi lichilnik zbilshuyetsya na 1 pri vihodi zmenshuyetsya Perehid do chekannya na podiyi yadra zdijsnyuyetsya lishe u vipadku yaksho znachennya zminnoyi lichilnika do sprobi zahoplennya bulo vzhe bilshe 1 tobto kritichna sekciya zajnyata i ye realne zmagannya dvoh abo bilshe potokiv za resurs kritichnoyi sekciyi Analogichnij ob yekt v Linux nazivayetsya f yuteks Porivnyannya kritichnih sekcij ta m yuteksivKritichna sekciya znachnoyu miroyu vikonuye ti zh zavdannya sho i m yuteks U operacijnih sistemah Microsoft Windows golovna vidminnist mizh m yuteksom i kritichnoyu sekciyeyu v tomu sho m yuteks ye ob yektom yadra i mozhe buti vikoristanij kilkoma procesami odnochasno kritichna sekciya zh nalezhit procesu i sluzhit dlya sinhronizaciyi tilki jogo potokiv Procedura vhodu i vihodu kritichnih sekcij zazvichaj zajmaye menshij chas nizh analogichni operaciyi m yuteksa Mizh m yuteksom i kritichnoyu sekciyeyu ye j terminologichni vidminnosti Procedura analogichna zahoplennyu m yuteksa nazivayetsya vhodom u kritichnu sekciyu znyattya blokuvannya m yuteksa vihodom z kritichnoyi sekciyi Robota z kritichnimi sekciyami u WindowsDlya roboti z kritichnimi sekciyami vikoristovuyut Windows API Pered vikoristannya kritichnoyi sekciyi yiyi slid inicializuvati za dopomogoyu proceduri InitializeCriticalSection Yiyi opis movoyu C void WINAPI InitializeCriticalSection out LPCRITICAL SECTION lpCriticalSection Opis movoyu Delphi procedure InitializeCriticalSection var lpCriticalSection TRTLCriticalSection Pered vhodom u kod kritichnoyi sekciyi potik maye viklikati funkciyu EnterCriticalSection Yiyi opis movoyu C void WINAPI EnterCriticalSection inout LPCRITICAL SECTION lpCriticalSection Yaksho v cej moment zhoden z potokiv procesu ne volodiye kritichnoyu sekciyeyu to vona staye vlasnikom yiyi ob yekta i prodovzhuye vikonannya Yaksho sekciya vzhe zahoplena inshim potokom viklikayuchij potik zupinyayetsya do yiyi zvilnennya Potik yakij volodiye kritichnoyu sekciyeyu mozhe povtorno viklikati EnterCriticalSection bez blokuvannya svogo vikonannya Vidrazu pislya zakinchennya roboti zi spilnim resursom potik povinen zvilniti ob yekt kritichnoyi sekciyi viklikom proceduri LeaveCriticalSection Yiyi opis movoyu C void WINAPI LeaveCriticalSection inout LPCRITICAL SECTION lpCriticalSection Opis movoyu Delphi procedure LeaveCriticalSection var lpCriticalSection TRTLCriticalSection Vona zvilnyaye ob yekt kritichnoyi sekciyi i yaksho v cej chas isnuyut inshi potoki yaki ochikuyut yiyi zvilnennya odna z nih staye novim vlasnikom i prodovzhuye vikonannya Yaksho potik zavershitsya ne zvilnivshi kritichnoyi sekciyi vona perehodit u neviznachenij stan i robota programi mozhe buti zablokovana Dlya kozhnoyi kritichnoyi sekciyi sistema pidtrimuye lichilnik vhodzhen tomu potik povinna zvilniti yiyi stilki raziv skilki zahoplyuvala Nedotrimannya ciyeyi umovi privede do blokuvannya potoku zavisannya Slid takozh pam yatati sho sproba vihodu z kritichnoyi sekciyi yakoyu potik ne volodiye takozh privede do blokuvannya viklikayuchogo potoku Programa mozhe zdijsniti sprobu zahoplennya ob yekta kritichnoyi sekciyi bez zupinki potoku Dlya cogo vikoristovuyut funkciyu TryEnterCriticalSection opis movoyu C BOOL WINAPI TryEnterCriticalSection inout LPCRITICAL SECTION lpCriticalSection Opis funkciyi na Delphi function TryEnterCriticalSection var lpCriticalSection TRTLCriticalSection BOOL U moment vikliku vona pereviryaye chi kritichna sekciya zahoplena yakimos inshim potokom Yaksho tak funkciya povertaye false u protilezhnomu vipadku vona zahoplyuye kritichnu sekciyu ta povertaye true Pislya zavershennya roboti z kritichnoyu sekciyeyu vona povinna buti vivilnena viklikom proceduri DeleteCriticalSection Opis na C void WINAPI DeleteCriticalSection inout LPCRITICAL SECTION lpCriticalSection Opis na Delphi procedure DeleteCriticalSection var lpCriticalSection TRTLCriticalSection Priklad vikoristannya kritichnoyi sekciyi Nizhche privedeno fragment kodu movoyu Delphi yakij zabezpechuye sinhronizaciyu roboti potoku pri zvertanni do spilnoyi dlya kilkoh potokiv zminnoyi A Zadlya usunennya neodnoznachnosti viklikanoyi konkurenciyeyu potokiv podibnij fragment programi povinen buti u vsih potokah yaki pracyuyut zi zminnoyu A Yaksho podibnoyi sinhronizaciyi ne vikoristovuvati to vinikatime konkurenciya potokiv Ogoloshennya kritichnoyi sekciyi var ICriSec TRTLCriticalSection Inicializaciya do zapusku pershogo potoku InitializeCriticalSection ICriSec Funkciya potoku function ThreadFunc Ptr Pointer LongInt var I integer begin for I 1 to 1000000 do begin Yakijs kod EnterCriticalSection ICriSec Inc A LeaveCriticalSection ICriSec Yakijs kod end end Znishennya ob yekta kritichnoyi sekciyi DeleteCriticalSection ICriSec PrimitkiKonovalenko I V Fedoriv P S Sistemne programuvannya u Windows z prikladami na Delphi T TNTU 2012 8 grudnya 2012 u Wayback Machine Arhiv originalu za 20 kvitnya 2012 Procitovano 29 kvitnya 2012 Arhiv originalu za 18 kvitnya 2012 Procitovano 29 kvitnya 2012 Arhiv originalu za 30 sichnya 2012 Procitovano 29 kvitnya 2012 Arhiv originalu za 20 kvitnya 2012 Procitovano 29 kvitnya 2012 Arhiv originalu za 22 kvitnya 2012 Procitovano 29 kvitnya 2012 Div takozhBagatonitevist potik Sinhronizaciya procesiv M yuteks Semafor programuvannya F yuteks shvidkij koristuvackij m yuteks Podiya Windows Cya stattya potrebuye dodatkovih posilan na dzherela dlya polipshennya yiyi perevirnosti Bud laska dopomozhit udoskonaliti cyu stattyu dodavshi posilannya na nadijni avtoritetni dzherela Zvernitsya na storinku obgovorennya za poyasnennyami ta dopomozhit vipraviti nedoliki Material bez dzherel mozhe buti piddano sumnivu ta vilucheno sichen 2016 Ce nezavershena stattya pro programuvannya Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi Ce nezavershena stattya pro operacijni sistemi Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi