Thread — process ichidagi mustaqil bajarilish oqimi. Bitta process bir yoki bir nechta threadga ega bo‘lishi mumkin.
Bir processdagi threadlar umumiy address space, heap, global o‘zgaruvchilar va ochiq file descriptorlarni bo‘lishadi. Har thread esa o‘z stacki, register holati va instruction pointeriga ega.
Threadlar parallel yoki navbatma-navbat bajarilib, applicationga bir vaqtning o‘zida bir nechta vazifani boshqarish imkonini beradi.
Process va thread
Process resurslar konteyneri, thread esa bajarilish birligi hisoblanadi.
| Xususiyat | Process | Thread |
|---|---|---|
| Address space | Alohida | Process ichida umumiy |
| Heap | Alohida | Umumiy |
| Stack | Har processda | Har threadda alohida |
| File descriptor | Processga tegishli | Threadlar bo‘lishadi |
| Yaratish xarajati | Kattaroq | Odatda kichikroq |
| Izolatsiya | Kuchliroq | Zaifroq |
Bir thread xotirani noto‘g‘ri o‘zgartirsa, butun processga ta’sir qiladi.
Main thread
Process ishga tushganda kamida bitta main thread yaratiladi.
Main thread:
- dastur entry pointini bajaradi;
- boshqa threadlarni yaratishi mumkin;
- event loopni ishga tushiradi;
- application lifecycle’ni boshqaradi.
Main thread tugashi bilan processning boshqa threadlari ham tugashi yoki runtime siyosatiga ko‘ra davom etishi mumkin.
Thread yaratish
Operatsion tizim yoki runtime thread yaratish API beradi.
Yangi threadga:
berilishi mumkin.
Juda ko‘p thread xotira va scheduler xarajatini oshiradi.
User thread va kernel thread
Kernel thread
Operatsion tizim scheduleriga ko‘rinadi. Har thread alohida CPUda bajarilishi mumkin.
User-level thread
Runtime foydalanuvchi muhitida rejalashtiradi. Bir yoki bir nechta kernel thread ustida ko‘p user thread ishlashi mumkin.
Til va runtime’ga qarab model farq qiladi.
Parallelizm va concurrency
Concurrency — bir nechta vazifa vaqt oralig‘ida oldinga siljishi.
Parallelism — vazifalarning ayni paytda turli CPU corelarda bajarilishi.
Bitta coreda threadlar context switch orqali concurrent ishlaydi. Ko‘p coreda parallel bajarilishi mumkin.
Scheduler
Kernel runnable threadlarni CPU corelarga taqsimlaydi.
Scheduler quyidagilarni hisobga oladi:
Process emas, ko‘p tizimlarda aynan thread schedulerning amaliy bajarilish birligi hisoblanadi.
Context switch
CPU bir threaddan boshqasiga o‘tganda:
saqlanadi va tiklanadi.
Bir process ichidagi thread switch processlararo switchdan yengilroq bo‘lishi mumkin, chunki address space o‘zgarmaydi. Baribir cache va scheduler xarajati mavjud.
Shared memory
Threadlar umumiy xotiradan tez aloqa qiladi.
Masalan, bitta thread queuega vazifa qo‘shadi, worker thread uni oladi.
Umumiy xotira bilan birga synchronization kerak. Aks holda race condition yuz beradi.
Race condition
Natija threadlar qaysi tartibda bajarilishiga bog‘liq bo‘lib qolsa race condition yuz beradi.
Misol:
counter = counter + 1
Bu amal o‘qish, qo‘shish va yozish bosqichlariga bo‘linishi mumkin. Ikki thread bir xil eski qiymatni o‘qib, bittasining yangilanishini yo‘qotadi.
Mutex, atomic operation yoki boshqa mexanizm ishlatiladi.
Thread safety
Funksiya bir nechta thread tomonidan bir vaqtda chaqirilganda to‘g‘ri ishlasa, thread-safe hisoblanadi.
Thread safety usullari:
Barcha library thread-safe emas.
Thread-local storage
Har thread uchun alohida qiymat saqlanadi.
Misollar:
- request context;
- error code;
- allocator cache;
- tracing ma’lumoti.
Thread poolda thread qayta ishlatilgani sabab eski thread-local holat keyingi requestga o‘tmasligi uchun tozalanadi.
Thread pool
Har vazifa uchun yangi thread yaratish o‘rniga oldindan worker threadlar yaratiladi.
Vazifalar queuega tushadi.
Afzalliklari:
- yaratish xarajati kamayadi;
- thread soni cheklanadi;
- resurs nazorat qilinadi.
Pool juda kichik bo‘lsa backlog, juda katta bo‘lsa context switch va memory sarfi oshadi.
I/O-bound va CPU-bound
I/O-bound vazifalar ko‘p vaqt network yoki diskni kutadi. Threadlar kutish paytida boshqa ish bajarishi mumkin.
CPU-bound vazifalar core vaqtini to‘liq ishlatadi. Thread sonini core sonidan haddan tashqari oshirish performance’ni pasaytiradi.
Stack
Har thread alohida stack oladi.
Stackda:
saqlanadi.
Juda chuqur recursion yoki katta local array stack overflowga sabab bo‘lishi mumkin.
Exception va signal
Bir threaddagi tutib olinmagan exception butun processni tugatishi mumkin.
Unix signal processga yuboriladi, ammo ma’lum threadda qayta ishlanishi mumkin.
Signal handler thread-safe bo‘lmagan funksiyalarni chaqirmasligi kerak.
Cancellation
Threadni tashqaridan majburan to‘xtatish lock va resurslarni ochiq qoldirishi mumkin.
Yaxshi model:
Thread xavfsiz nuqtada ishini tugatadi.
Diagnostika
Ko‘p threaddagi muammoda:
- thread count;
- CPU;
- stack trace;
- blocked lock;
- race;
- deadlock;
- context switch;
- pool queue;
- affinity;
- thread-local state
tekshiriladi.
Thread dump qaysi thread qayerda kutayotganini ko‘rsatadi.
Thread nomi va kuzatuv
Threadga tushunarli nom berish profiler, crash dump va log tahlilini yengillashtiradi.
Masalan:
http-worker-3;db-writer;metrics-loop;scheduler.
Nomsiz yuzlab worker orasida qaysi vazifa bloklanganini topish qiyin. Runtime thread ID bilan operatsion tizim thread ID bir xil bo‘lmasligi mumkin.
CPU affinity
Threadni ma’lum CPU core yoki core guruhiga bog‘lash affinity deb ataladi. Cache locality va real-time workload uchun foydali, ammo noto‘g‘ri pinning yukni notekis taqsimlaydi.
Bog‘liq tushunchalar
Process, Scheduler, Context switch, Mutex, Semaphore, Race condition, Thread pool, Stack, Atomic operation, Coroutine