Semaphore — bir yoki bir nechta bajarilish oqimining umumiy resursga kirishini hisoblagich orqali boshqaradigan synchronization mexanizmi.
Semaphore qiymati mavjud ruxsatlar sonini bildiradi. Thread yoki process resurs olishda hisoblagichni kamaytiradi, bo‘shatishda oshiradi.
Semaphore mutexdan farqli ravishda bir vaqtning o‘zida bir nechta foydalanuvchiga ruxsat berishi mumkin.
Asosiy amallar
Klassik nomlar:
wait,P,down— ruxsat olish;post,V,up— ruxsatni qaytarish.
Agar qiymat 0 bo‘lsa, wait qilgan thread kutadi.
post qiymatni oshiradi va kutayotganlardan birini uyg‘otishi mumkin.
Counting semaphore
Qiymat 0dan katta bo‘lishi mumkin.
Masalan, database connection poolda 10 ta connection mavjud.
Semaphore boshlang‘ich qiymati:
10
Har worker connection olganda wait, qaytarganda post qiladi.
Bir vaqtda 10 tadan ko‘p worker resursga kirmaydi.
Binary semaphore
Qiymat 0 yoki 1.
U mutual exclusionga o‘xshash ishlashi mumkin.
Biroq binary semaphore va mutex semantik jihatdan bir xil emas. Semaphore’ni olgan threaddan boshqa thread ham post qilishi mumkin. Mutex odatda owner tushunchasiga ega.
Producer va consumer
Bounded bufferda ikki semaphore ishlatilishi mumkin.
empty— bo‘sh slotlar;full— tayyor elementlar.
Producer:
emptyni kamaytiradi.- bufferga yozadi.
fullni oshiradi.
fullni kamaytiradi.- bufferdan oladi.
emptyni oshiradi.
Bufferning o‘zi uchun mutex ham kerak bo‘lishi mumkin.
Resource pool
Semaphore cheklangan resurslarni boshqaradi:
- database connection;
- worker slot;
- network request;
- GPU job;
- file handle;
- API parallelism;
- queue capacity.
Bu loadni cheklab, resurs exhaustionni kamaytiradi.
Thread semaphore
Bir process ichidagi threadlar umumiy semaphore obyektidan foydalanadi.
Runtime yoki OS kutayotgan threadni sleeping holatiga o‘tkazadi.
Busy waiting o‘rniga CPU boshqa vazifaga beriladi.
Process-shared semaphore
Semaphore bir nechta process o‘rtasida shared memory yoki kernel obyekt orqali ishlashi mumkin.
Turlari:
Named semaphore tizim namespace’ida nom bilan topiladi.
Initial value
Boshlang‘ich qiymat noto‘g‘ri bo‘lsa, synchronization buziladi.
- 0 — signal kelguncha hech kim o‘tmaydi;
- 1 — bitta ruxsat;
- N — N ta parallel foydalanuvchi.
Qiymat resursning real capacity’siga mos bo‘lishi kerak.
Signal mexanizmi
Semaphore faqat resurs count uchun emas, hodisani bildirish uchun ham ishlatiladi.
Thread A ish tugagach post qiladi. Thread B waitdan uyg‘onadi.
Bunda boshlang‘ich qiymat 0.
Timeout
Cheksiz kutish o‘rniga timed wait ishlatilishi mumkin.
Timeout:
ni aniqlashga yordam beradi.
Timeoutdan keyin olingan resurs yo‘q, shuning uchun post qilinmaydi.
Try wait
Non-blocking try_wait semaphore mavjud bo‘lsa oladi, aks holda darhol xato qaytaradi.
Bu fallback yoki boshqa ish bajarish uchun qulay.
Semaphore leak
Thread wait bilan ruxsat olib, xato yo‘lida post qilmasa, qiymat asta-sekin kamayadi.
Oxirida barcha worker kutib qoladi.
Cleanup finally, RAII yoki defer orqali kafolatlanadi.
Over-release
Olmagan ruxsatni post qilish hisoblagichni haqiqiy capacity’dan oshiradi.
Natijada resursdan ruxsat etilganidan ko‘p thread foydalanadi.
Ba’zi implementation maksimum qiymatni tekshiradi, boshqasi faqat katta counter saqlaydi.
Fairness
Semaphore kutayotgan threadlarni FIFO tartibida uyg‘otishi shart emas.
Yuqori yukda ayrim thread uzoq kutishi mumkin.
Fair semaphore qo‘shimcha queue semantikasini beradi, lekin overhead oshadi.
Priority inversion
Past priority thread resursni olgan, yuqori priority thread semaphore’da kutgan bo‘lishi mumkin.
Agar past priority thread CPU ololmasa, yuqori priority ham bloklanadi.
Mutexlarda priority inheritance bo‘lishi mumkin. Oddiy semaphore’da bu har doim mavjud emas.
Deadlock
Bir nechta semaphore turli tartibda olinsa deadlock yuz beradi.
Thread A S1ni, keyin S2ni kutadi. Thread B S2ni, keyin S1ni kutadi.
Global lock order va timeout xavfni kamaytiradi.
Semaphore va mutex
| Jihat | Semaphore | Mutex |
|---|---|---|
| Hisoblagich | 0..N | Odatda locked/unlocked |
| Owner | Majburiy emas | Odatda bor |
| Bir nechta ruxsat | Bor | Yo‘q |
| Signal berish | Qulay | Asosiy vazifa emas |
| Priority inheritance | Har doim emas | Bo‘lishi mumkin |
Async semaphore
Async runtime’da semaphore kutish paytida threadni bloklamaydi. Coroutine suspend bo‘ladi.
Bu bir vaqtda bajariladigan HTTP request yoki task sonini cheklashda ishlatiladi.
Cancellationda ruxsat to‘g‘ri qaytarilishi muhim.
Monitoring
Semaphore bevosita ko‘rinmasa ham quyidagilar kuzatiladi:
- active permit;
- waiters;
- wait time;
- timeout;
- pool utilization;
- acquire failure.
Doim 100% band semaphore capacity yetishmasligi yoki resurs sizishini ko‘rsatadi.
Diagnostika
Semaphore muammosida:
- initial value;
- acquire va release soni;
- error path;
- waiters;
- timeout;
- ownerga teng mantiq;
- lock order;
- cancellation;
- process crash
tekshiriladi.
Named semaphore process crashidan keyin qolib ketishi mumkin.
Capacity tanlash
Semaphore qiymati tasodifiy katta qo‘yilmaydi. U backend capacity, CPU, database connection va latency testlariga tayangan holda tanlanadi.
Juda katta limit overloadni ichkariga o‘tkazadi. Juda kichik limit resurs bo‘sh bo‘lsa ham throughputni cheklaydi.
Dynamic tizimlarda limit metriclar asosida boshqarilishi mumkin, ammo keskin o‘zgarish navbatni beqaror qiladi.
Shutdown
Service yopilganda yangi acquire to‘xtatiladi, mavjud permit egalari ishini tugatadi. Kutayotgan tasklar cancellation yoki aniq xato oladi. Aks holda shutdown abadiy kutib qolishi mumkin.
Bog‘liq tushunchalar
Synchronization, Mutex, Counting semaphore, Binary semaphore, Thread, Process, Deadlock, Resource pool, Condition variable