Відмінності між версіями «Потоки та нитки в Microsoft Windows»

Матеріал з Вікі ЦДУ
Перейти до: навігація, пошук
Рядок 37: Рядок 37:
 
унікальний ідентифікатор ниті;
 
унікальний ідентифікатор ниті;
 
іноді ниті мають свій контекст захисту, який використовується багатонитевими серверними програмами, що підміняють контекст захисту клієнтів.
 
іноді ниті мають свій контекст захисту, який використовується багатонитевими серверними програмами, що підміняють контекст захисту клієнтів.
 +
'''Стани нитей'''
 +
Initialized (ініціалізована). У цей стан нить входить у процесі свого створення.
 +
Ready (готова). Нить у стані готовності очікує виконання. Вибираючи наступну нить для виконання, диспетчер бере до уваги тільки пул нитей, готових до виконання.
 +
Standby (простоює). Нить у цьому стані вже обрана наступною для виконання на конкретному процесорі. У підходящий момент диспетчер перемикає контекст на цю нить. У стані Standby може перебувати тільки одна нить для кожного процесора в системі. Проте нить може бути витиснена навіть у цьому стані (якщо, наприклад, до початку виконання такої ниті до виконання буде готова нить з вищим пріоритетом).
 +
Running (виконується). Нить переходить у цей стан і починає виконуватися відразу після того, як диспетчер перемикає на неї контекст. Виконання ниті припиняється, коли вона завершується, витісняється ниттю з вищим пріоритетом, перемикає контекст на іншу нить, самостійно переходить у стан очікування або минає виділений йому квант процесорного часу (та інша нить з тим же пріоритетом готова до виконання).
 +
Waiting (очікує). Нить входить у цей стан кількома способами. Вона може самостійно почати очікування на синхронізуючому об'єкті або його змушує до цього підсистема оточення. Після закінчення очікування  — залежно від пріоритету — або негайно починає виконуватися, або переходить у стан Ready.
 +
Transition (перехідний стан). Нить переходить у цей стан, якщо вона готова до виконання, але її стек ядра вивантажений з пам'яті. Щойно цей стек завантажується у пам’ять, нить переходить у стан Ready.
 +
Terminated (завершений). Закінчуючи виконання, нить переходить у стан Terminated. Після цього інформація про нить у виконавчій системі може бути знищена.
 +
Можливі переходи між станами нитей показано на діаграмі.
 +
 +
[[Файл:niti.jpg]]

Версія за 22:19, 14 квітня 2013

Нить (англ. thread) або повніше нить виконання (англ. thread of execution), часто застосовується потік (програмний потік) та англіцизм тред — в інформатиці так називається спосіб програми розщепити себе на дві чи більше одночасні (чи псевдо-одночасні) задачі. Реалізація нитей та процесів відрізняються в різних операційних системах, але загалом нить міститься всередині процесу і різні ниті одного процесу спільно розподіляють деякі ресурси, в той час як різні процеси ресурси не розподіляють. В системах з одним процесором багатонитевість реалізується загалом поділом часу виконання («кванти часу»), дуже подібно до паралельного виконання багатьох задач: процесор послідовно переключається між різними нитями. Це переключення контексту відбувається настільки швидко, що у кінцевого користувача створюється ілюзія одночасного виконання. На багатопроцесорних чи на багатоядерних системах робота нитей здійснюється справді одночасно, бо різні ниті і процеси виконуються буквально одночасно різними процесорами або ядрами процесора. Особливості квантування в опраційній системі Windows розглянуто у статті Квант (Windows). Багато сучасних операційних систем прямо підтримують квантування часу і багатопроцесорну роботу нитей через планувальник процесів. Ядро операційної системи дозволяє програмісту маніпулювати нитями через інтерфейс системних викликів. Деякі реалізації викликають ниті ядра, оскільки легковагові процеси (англ. lightweight process, LWP) є спеціальним типом нитей ядра, що розподіляють деякі стани і інформацію. Поза тим, програма може емулювати роботу нитей, використовуючи таймер, сигнали або інші методи, щоб перервати власне виконання і послідовно виконувати різні задачі власним квантуванням часу. Такий спосіб іноді зветься нитями користувацького простору (англ. user-space threads) або волокнами.

220px.png

Порівняння нитей з процесами

Ниті відрізняються від традиційних процесів багатозадачних операційних систем, в тому що процеси: на загал, незалежні, дублюють значну частину інформації про стан, мають окремий адресний простір, взаємодіють тільки через системні міжпроцесорні механізми комунікацій. Ниті всередині процесу, з іншої сторони, розподіляють інформацію про стан процесу, і прямо доступаються до спільної пам'яті та інших ресурсів. Переключення контексту між нитями процеса на загал швидше, ніж переключення контексту між процесами. Описуючи ситуацію такі системи, як Windows NT та OS/2, кажуть, що мають «дешеві» ниті та «дорогі» процеси; в інших операційних системах ситуація не дуже відмінна.

Багатонитевість є популярною моделлю програмування і виконання, бо дозволяє багатьом нитям існувати всередині контексту одного процесу, розподіляючи ресурси процесу, але виконуючись незалежно. Нитева модель програмування забезпечує розробникам корисні абстракції для паралельного виконання. Проте, можливо найцікавіше застосування технології в випадку, коли один процес виконується на багатопроцесорній системі. Ця перевага багатонитевих програм дозволяє їм скоріше виконуватися на комп'ютерах з кількома процесорами, процесорами з кількома ядрами, або на кластері машин, бо ниті програми природно надають собі можливість справді паралельного виконання. У такому випадку програміст має бути особливо обережним, щоб уникнути стану гонитви та інших непередбачених поведінок. Для забезпечення коректної роботи з даними, ниті часто потребують процедури доступу до даних в певному порядку. Ниті також вимагають атомарних операцій (часто реалізованих з використанням семафорів), щоб уникнути одночасної неузгодженої модифікації даних або їхнього читання, в той час як процес модифікує дані. Недбале поводження з такими примітивами може призвести до взаємного блокування. Планувальники операційних систем переключають ниті одним з двох можливих способів. Запобіжна або витісняюча багатонитевість загалом розглядається як кращий підхід, бо вона дозволяє операційній системі визначити, коли може статися перемикання контексту. На противагу, кооперативна багатонитевість покладається на самі ниті, щоб вони передали контроль виконання на точках зупину. Це може створити проблеми, якщо нить чекає на ресурс, який став недоступним. Недолік запобіжної багатонитевості в тому, що перемикання контексту може статися в недоречну мить, спричиняючи пріоритетну інверсію або інші погані ефекти, яких можна уникнути в кооперативній багатонитевості. Традиційно базове комп'ютерне апаратне забезпечення не надавало багато підтримку багатонитевості, оскільки переключення між нитями загалом є вже скорішою процедурою порівняно з переключенням контексту процесів. Процесори вбудованих систем, що мають більші вимоги до поведінки в реальному часі, можуть мати апаратну підтримку багатонитевості зменшенням часу перемикання, можливо розміщуючи виділений блок регістрів для кожної ниті, замість того, щоб зберігати/читати загальні регістри. На кінці 1990-х стала відома ідея виконання інструкцій з різних нитей одночасно, це зветься одночасною багатонитевостю. Ця можливість була введена в процесорі Intel Pentium 4 під ім'ям Hyper-threading.

Переваги багатонитевості Багатонитевість програми створює підґрунтя для реалізації реальної багатозадачності — виконання кількох завдань одночасно (якщо обчислювальна система є багатопроцесорною), або «псевдоодночасно» («майже одночасно») на однопроцесорних системах. Наявність кількох нитей дозволяє: Оптимізувати організацію поведінки програми. Часто поведінка програми може бути організована у кілька незалежних паралельних алгоритмів, тоді їх можна винести в окремі ниті. При цьому їм можна задавати різний пріоритет виконання. Обходити критичні до часу операції. Якщо програма має лише одну нить, то вона повинна зупинити все виконання при очікуванні повільних операцій, таких як запис у файл чи відображення засобами мультимедіа. При цьому процесор перебуває у простої, поки ця операція не завершиться. Якщо застосунок складається з кількох нитей, він може продовжувати виконання в окремих нитях, коли одна нить очікуватиме на завершення повільної операції. Реалізувати багатопроцесорну обробку. Якщо система, у якій працює програма, є мультипроцесорною, то можна сповна скористатися наявними обчислювальними ресурсами і підвищити її ефективність використанням кількох нитей. При цьому різні ниті можуть виконуватися одночасно на різних процесорах. Таким чином, доцільне використання нитей може значно поліпшити продуктивність і зручність використання програм. На одному процесорі багатонитевість відбувається шляхом тимчасової активізації різних нитей. Таке перемикання відбувається досить часто, щоб користувач сприймав виконання нитей як одночасне. У багатопроцесорних і багатоядерних системах ниті можуть реально виконуватися одночасно, при цьому кожен процесор або ядро обробляє окрему нить (або кілька нитей).

Загальна характеристика нитей Хоча в кожної ниті свій контекст виконання, кожна нить усередині одного процесу використовує його віртуальний адресний простір (а також інші ресурси, які належать процесу). Це означає, що всі ниті в процесі можуть записувати й зчитувати вміст пам'яті інших нитей цього процесу. Але ниті не можуть посилатися на адресний простір іншого процесу. Виняток може бути в ситуації, коли процес надає частину свого адресного простору як розділ загальної пам'яті через об'єкт «проектований файл» (file mapping object), або коли один із процесів має право на відкриття іншого процесу й використовує функції доступу до пам'яті між процесами. За замовчуванням у ниті немає власного маркера доступу, але він може отримати його, і це дозволить йому підміняти контекст захисту іншого процесу. Нить містить такі важливі елементи: завантажений для виконання код; вміст набору регістрів процесора, що відображають стан процесора; два стеки, один із яких використовується ниттю при виконанні в режимі ядра, а інший — у користувацькому режимі; закриту область пам'яті, яку називають локальною пам'яттю ниті (thread-local storage, TLS); вона використовується підсистемами, бібліотеками виконавчих систем (run-time libraries) і DLL; унікальний ідентифікатор ниті; іноді ниті мають свій контекст захисту, який використовується багатонитевими серверними програмами, що підміняють контекст захисту клієнтів. Стани нитей Initialized (ініціалізована). У цей стан нить входить у процесі свого створення. Ready (готова). Нить у стані готовності очікує виконання. Вибираючи наступну нить для виконання, диспетчер бере до уваги тільки пул нитей, готових до виконання. Standby (простоює). Нить у цьому стані вже обрана наступною для виконання на конкретному процесорі. У підходящий момент диспетчер перемикає контекст на цю нить. У стані Standby може перебувати тільки одна нить для кожного процесора в системі. Проте нить може бути витиснена навіть у цьому стані (якщо, наприклад, до початку виконання такої ниті до виконання буде готова нить з вищим пріоритетом). Running (виконується). Нить переходить у цей стан і починає виконуватися відразу після того, як диспетчер перемикає на неї контекст. Виконання ниті припиняється, коли вона завершується, витісняється ниттю з вищим пріоритетом, перемикає контекст на іншу нить, самостійно переходить у стан очікування або минає виділений йому квант процесорного часу (та інша нить з тим же пріоритетом готова до виконання). Waiting (очікує). Нить входить у цей стан кількома способами. Вона може самостійно почати очікування на синхронізуючому об'єкті або його змушує до цього підсистема оточення. Після закінчення очікування — залежно від пріоритету — або негайно починає виконуватися, або переходить у стан Ready. Transition (перехідний стан). Нить переходить у цей стан, якщо вона готова до виконання, але її стек ядра вивантажений з пам'яті. Щойно цей стек завантажується у пам’ять, нить переходить у стан Ready. Terminated (завершений). Закінчуючи виконання, нить переходить у стан Terminated. Після цього інформація про нить у виконавчій системі може бути знищена. Можливі переходи між станами нитей показано на діаграмі.

Niti.jpg