Bosh sahifa Wiki Condition variable

Condition variable

Condition variable — oqimga umumiy holat ma’lum shartga kelguncha samarali kutish va boshqa oqim holatni o‘zgartirganda uyg‘onish imkonini beradigan sinxronizatsiya primitivi. U odatda mutex bilan birga ishlaydi. Condition variable ma’lumotning o‘zi yoki hodisalar sanog‘i emas; haqiqiy shart alohida umumiy o‘zgaruvchida ifodalanadi.

Kutish amali

Oqim mutexni oladi va predicate, masalan, “navbat bo‘sh emas” shartini tekshiradi. Shart yolg‘on bo‘lsa, wait mutexni atomar ravishda bo‘shatib, oqimni uxlatadi. Atomarlik muhim: mutexni bo‘shatish bilan uxlash orasida signal yo‘qolib qolmasligi kerak. Uyg‘ongach oqim mutexni qayta oladi va shartni yana tekshiradi.

mutexni ol
while navbat bo‘sh:
    condition.wait(mutex)
elementni ol
mutexni bo‘shat

Tekshiruv if emas, while bilan yoziladi. Spurious wakeup signal bo‘lmasa ham sodir bo‘lishi mumkin. Bundan tashqari, uyg‘ongan oqim mutexni olishidan oldin boshqa oqim resursni iste’mol qilib qo‘yishi mumkin. Predicate qayta tekshirilsa, ikkala holat xavfsiz boshqariladi.

Signal berish

Ishlab chiqaruvchi mutex ostida umumiy holatni o‘zgartiradi, so‘ng signal bilan bitta yoki broadcast bilan barcha kutuvchini uyg‘otadi. Signal conditionni “yoqilgan” holatda saqlamaydi. Hech kim kutmayotgan paytdagi signal keyingi kutuvchi uchun eslab qolinmasligi mumkin; shuning uchun qaror doim predicatega asoslanadi.

Bir kutuvchi ishni davom ettirishi yetarli bo‘lsa signal samaraliroq. Bir o‘zgarish turli predicatega ta’sir qilsa yoki bir nechta resurs paydo bo‘lsa broadcast kerak bo‘lishi mumkin. Barcha oqimni uyg‘otish thundering herd hosil qilib, ular bir mutex uchun raqobatlashishiga olib keladi.

Producer-consumer misoli

Chegaralangan navbatda ikki condition ishlatilishi mumkin: not_empty iste’molchilarni, not_full ishlab chiqaruvchilarni kutdiradi. Element qo‘shilganda not_empty, element olinganda not_full signal qilinadi. Navbat holati faqat bitta mutex bilan himoyalansa, sig‘im va indeks invariantlari izchil qoladi.

Timeoutli kutish xizmatning abadiy bloklanishini cheklaydi. Vaqt hisobida tizim soati orqaga o‘zgarishidan ta’sirlanmaydigan monoton soat ishlatiladi. Timeout bo‘lgach ham predicate qayta tekshiriladi, chunki signal va muddat deyarli bir vaqtda kelishi mumkin.

Xatolar

Conditionni mutexsiz tekshirish data race va yo‘qolgan uyg‘otishga olib keladi. Noto‘g‘ri mutex bilan kutish ham umumiy holatga atomar bog‘lanishni buzadi. Signalni holatni o‘zgartirishdan oldin berish uyg‘ongan oqimning eski predicate ko‘rishiga sabab bo‘lishi mumkin.

Condition variable semaphorega o‘xshamaydi: semaphore ruxsatlar sonini saqlaydi, condition esa tashqi predicate o‘zgargan bo‘lishi mumkinligini bildiradi. Tanlov hodisani sanash kerakmi yoki himoyalangan holatni kutish kerakmi degan savolga bog‘liq.

Monitor va bekor qilish

Monitor umumiy holat, mutex va unga tegishli conditionlarni bitta abstraksiyada birlashtiradi. Barcha o‘zgartirish monitor metodlari ichida bajarilsa invariantni ko‘rish osonlashadi. Kutayotgan oqimni shutdown paytida uyg‘otish uchun predicate tarkibiga stopping holati qo‘shiladi va broadcast beriladi. Faqat threadni tashqaridan majburan tugatish qulf va resursni noma’lum holatda qoldirishi mumkin. Condition destructiondan oldin hech bir oqim kutmayotgani kafolatlanadi. Cancellation signal bilan bir vaqtda kelsa, mutex ostidagi holat qaysi natija ustunligini belgilaydi. Bu qoida hujjatlashtirilmasa, yopilishdagi kam uchraydigan poyga paydo bo‘ladi.

Bir nechta condition bir holatga bog‘liq bo‘lsa, qaysi o‘zgarish qaysi kutuvchini uyg‘otishi aniqlanadi. Noto‘g‘ri signal funksional xato bermasdan ortiqcha context switch va kechikish yaratishi mumkin. Kutish vaqti metrikasi lock contentiondan predicate uzoq vaqt o‘zgarmayotganini ajratishga yordam beradi.

Bog‘liq tushunchalar

Mutex, Critical section, Semaphore, Monitor, Spurious wakeup, Producer-consumer