Oqimlar guruhi. Murakkab masalalarda, masalan, ko'p sonli turli jinsli oqimlarni modellashtirish masalalarida, ularni oqimlar guruhi konsepsiyasi yordamida tuzish kerak - bu o'z nomiga ega bo'lgan oqimlar to'plami, qaysi guruhning oqimlari ustida operatsiyalar aniqlanganligini bildiradi. Oqimlar guruhlari Javada (ThreadGroup sinfi yordamida) eng muvaffaqiyatli tatbiq etilgan. Shuningdek, .NETda ham oqimlar o’qi (ThreadPool) yordamida samarali tatbiq qilingan.
Oqimlarning lokal ma’lumotlari (thread-local storage - TLS) – faqat aniq bir oqimga tegishli bo’lgan ma’lumotlar va faqat shu oqimlar ishlatadigan ma’lumotlar. Bunday ma'lumotlarga ehtiyoj juda katta, chunki ko’poqimllik katta masalalar yechimini parallellashtirishning juda muhim usuli bo'lib, unda har bir oqim o'ziga yuklangan qismvazifani hal qilish uchun ishlaydi. Barcha zamonaviy operatsion tizimlar va dasturiy ta'minotni ishlab chiqish platformalari lokal oqim ma'lumotlari konsepsiyasini qo'llab-quvvatlaydi.
Oqimlarni sinxronlash. Jarayonlardagi singari, oqimlardan ham umumiy resurslardan foydalanishi va umumiy xabarlarga javob berishi mumkin bo'lganligi sababli, ularni sinxronlashtirish vositasi zarur bo’ladi.
Tupiklar (deadlocks) va ularning oldini olish. Jarayonlar kabi oqimlar ham o’zaro bir birini bloklashi mumkin (ya’ni, deadlock holati hosil bo’lishi mumkin).
POSIX (Pthreads) oqimlari
Ko’poqimlilikga aniq misol sifatida POSIX ning ko’p oqimliligini qarab chiqamiz (Portable Operating Systems Interface of uniX kind – UNIX turidagi ko’chuvchan OT lar uchun standartlar). POSIX-da ko'p oqimli ishlov berish IEEE 1003.1c standarti tomonidan belgilanadi, u oqimlarni yaratish va sinxronlashtirish uchun API-ni tavsiflaydi. Shuni esda tutingki, POSIX-standarti API faqat oqim kutubxonasi uchun kerakli xatti-harakatni belgilaydi. Oqimlarni amalga oshirish muayyan POSIX talablariga javob beradigan kutubxona mualliflarining ixtiyorida bo’ladi. POSIX-oqimlar UNIX turidagi OTlarda tarqalgan, shuningdek, ko’plab OT larda dasturlarning xamkorligi maqsadida qo’llaniladi, masalan, Solaris va Windows NT.
POSIX standarti oqimlar uchun ma’lumotlarning asosiy ikkita turini aniqlaydi: pthread_t – oqim deskriptori; pthread_attr_t – oqim atributlari to’plami.
Oqimlarni boshqarish uchun POSIX standarti quyidagi funktsiyalar to’plamiga mosashtirilgan:
· pthread_create(): oqimni hosil qilish
· pthread_exit(): oqimni tugatish (tugallanganda oqim funktsiyasi tomonidan chaqirilish shart)
· pthread_cancel(): oqimni inkor qilish
· pthread_join(): funksiya chaqiruvida ko'rsatilgan boshqa bir ish tugaguniga qadar oqimning bajarilishini bloklash
· pthread_detach(): oqimlar band qilib turgan resurslarni bo’shatish (agar oqim bajarilayotgan bo’lsa, u holda resursni bo’shatish u yakunlangandan keyin amalga oshiriladi)
· pthread_attr_init(): oqimning atributlar strukturasini ishga tushirish
· pthread_attr_setdetachstate(): tizimga oqim tugagandan so'ng, u avtomatik ravishda oqim egallagan resurslarni bo'shatishi mumkinligini ko’rsatish
· pthread_attr_destroy(): xotirani oqim atributlari tuzilmasidan bo’shatish (deskriptor ni o’chirish).
Mutexes (mutexes) - semafor analoglari va shartli o'zgaruvchilar (conditional variables) yordamida POSIX oqimlarini sinxronlash uchun quyidagi primitivlar mavjud:
· - pthread_mutex_init() – myuteksni hosil qilish;
· - pthread_mutex_destroy() – myuteksni o’chirish;
· - pthread_mutex_lock() – myuteksni yopish;
· - pthread_mutex_trylock() – muteksni sinovdan yopish (agar u allaqachon yopilgan bo'lsa, chaqiruv e'tiborsiz qoldiriladi va oqim bloklanmaydi);
· - pthread_mutex_unlock() – myuteksni ochish;
· - pthread_cond_init() – shartli o’zgaruvchilarni hosil qilish;
· - pthread_cond_signal() – shartli o’zgaruvchilarni blokdan chiqarish;
· - pthread_cond_wait() – shartli o’zgaruvchilar bo’yicha kutish.
С++ tilida POSIX-oqimlarining qo’llanilishiga misol:
#include
#include
#include
#include
static void wait_thread(void) {
time_t start_time = time(NULL);
while (time(NULL) == start_time) {
//protsessorni 1 sekundgacha band qilishdan tashqari birorta harakat yo’q.
}
}
static void *thread_func(void *vptr_args)
{ int i;
for (i = 0; i < 20; i++) {
fputs(" b\n", stderr);
wait_thread();
}
return NULL;
}
int main(void) {
int i;
pthread_t thread;
if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
return EXIT_FAILURE;
}
for (i = 0; i < 20; i++) {
puts("a");
wait_thread();
}
if (pthread_join(thread, NULL) != 0) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Misolda "a" harflari ketma-ketligini standart chiqishga chiqaradigan asosiy oqimning va "b" harflari ketma-ketligini standart xato oqimiga (stderr) chiqaradigan qism oqimning parallel bajarilishi tasvirlangan. Oqimni yaratish xususiyatlariga (pthread_create) e'tibor bering, uning tanasini (thread_func-ning bajariladigan protsedurasi) belgilang va tugallanayotgan oqimni (pthread_join) kuting.
Solaris OTda jarayonlar va oqimlar
Solaris OT da yuqorida aytib o’tilganidek, ko’p oqimlilikning ko’pga/ko’p modeli ishlatiladi. Bundan tashqari tizimda bizga ma’lum bo’lgan jarayonlarni yengillashtirish (lightweight process) tushunchasi tizimli oqim va foydalanuvchi oqimining o’rtasidagi o’rta kontseptsiya sifatida ishlatiladi. Shunday qilib, Solaris OT da har bir foydalanuvchi oqimi o’zining yengil jarayonini aks ettiradi, bu esa o’z navbatida yadro oqimiga to’g’ri keladi; ikkinchisi kompyuter tizimining istalgan protsessorida (yoki protsessor yadrosida) bajarilishi mumkin. Solaris OTdagi oqimlarning tashkil etilishi sxemasi 9-rasmda keltirilgan.
9-rasm. Solaris oqimlar sxemasi.
Solaris OT da jarayonlarni tashkil etish sxemasi 10-rasmda tasvirlangan.
10-rasm. Solaris da jarayonlar.
Sxema shuni ko'rsatadiki, har bir jarayonda jarayonni boshqarish blokining standart ma'lumotlaridan tashqari, ularni boshqarish uchun barcha yengil jarayonlari ro'yxati ham mavjud.
Do'stlaringiz bilan baham: |