Starvation mobil ilovalarda — mohiyati, kelib chiqish sabablari va thread ochligining oldini olish usullari

Muallif: IT Sectr Nashr etilgan: 2026-03-18 O'qish vaqti: 10 daq

Starvation (thread ochligi) — bu thread ishni davom ettirish uchun zarur bo'lgan resursga kirish ololmaydigan, garchi u o'zi bajarishga tayyor bo'lgan vaziyatdir. Baeldung (Java Thread Starvation, 2024) ga ko'ra, ochlik adolatsiz rejalashtirish tufayli yuzaga keladi, past prioritetli threadlar doimiy ravishda yuqori prioritetlilar foydasiga kechiktiriladi. Deadlockdan farqli o'laroq, Starvation threadni bloklamaydi — u RUNNABLE holatida qoladi, lekin hech qachon protsessor vaqtini olmaydi.

Asosiy ma'lumotlar

  • Starvation — thread bajarishga tayyor bo'lishiga qaramay resursga kirish ololmaydigan vaziyat
  • Deadlockdan farqli o'laroq, ochlik vaqtida thread RUNNABLE holatida qoladi — bloklanmagan, lekin rivojlanmaydi
  • Adolatsiz rejalashtirish (masalan, synchronized orqali sinxronizatsiya) — JVMda Starvationning asosiy sababi
  • Fair Lock (ReentrantLock(true)) qulfga kirish uchun navbat tartibida adolatli kirishni kafolatlaydi
  • Thread Priority mobil ishlanmada o'zgartirilmasligi tavsiya etiladi — Android Runtime o'zi prioritetlarni boshqaradi

Starvation nima?

Starvation (thread ochligi) — bu ko'p threadli dasturlash muammosi bo'lib, unda thread vazifani bajarish uchun zarur resursga kirish ololmaydi, garchi resurs boshqa thread tomonidan abadiy bloklanmagan bo'lsa. Thread RUNNABLE holatidadir, lekin rejalashtiruvchi yoki sinxronizatsiya mexanizmi uning bajarilishini boshqa threadlar foydasiga muntazam ravishda kechiktiradi.

Mobil ishlanmada Starvation notekis vazifa bajarilishi sifatida namoyon bo'ladi: ba'zi operatsiyalar bir zumda bajariladi, boshqalari — halokatli kechikishlar bilan. Masalan, ma'lumotlarni sinxronlashtiradigan fon threadi, UI thread va animatsiya ishlovchilari uni doimiy ravishda ortda qoldirsa, ma'lumotlar bazasiga kirish ololmasligi mumkin. Android Developer Blog (Performance Matters, 2023) ma'lumotlariga ko'ra, Androidda o'tkazib yuborilgan kadrlarning (jank) taxminan 12% i renderlash bog'liq bo'lgan fon vazifalarining Starvationi tufayli yuzaga keladi.

Starvationning Deadlockdan asosiy farqi — qaytariluvchanlik. Agar tizim yuki kamaysa yoki prioritetlar qayta taqsimlansa, ochlik chekayotgan thread resursni olib ishni tugatishi mumkin. Biroq doimiy yuqori yuk sharoitida Starvation cheksiz davom etishi mumkin, muzlatilgan ilova taassurotini yaratadi.

Thread ochligining sabablari

Adolatsiz qulflar (Non-Fair Locks)

Java va Kotlinda synchronized — adolatsiz mexanizmning klassik namunasidir. Yuqori raqobatda JVM bir xil faol threadlarga qulfni cheksiz berishi mumkin, boshqa threadlar esa doimo poygada yutqazadi. Bu JVM xatosi emas, balki amalga oshirish xususiyatidir: adolatsiz qulflar kirishning bir xilligi hisobiga yuqori o'tkazish qobiliyatini ta'minlaydi. 4-8 threadli mobil ilovalar uchun bu muammo ayniqsa dolzarbdir.

Prioritetlardan noto'g'ri foydalanish

Turli thread prioritetlarini o'rnatish past prioritetli threadlarning Starvationiga olib kelishi mumkin. Android Runtime da Linuxning CFS (Completely Fair Scheduler) rejalashtiruvchisi protsessor vaqtini prioritetlarga mutanosib ravishda taqsimlaydi va agar yuqori prioritetli threadlar doimiy faol bo'lsa, past prioritetlilar hech qachon CPU ololmasligi mumkin. Google Androidda thread prioritetlarini o'zgartirishni qat'iy tavsiya etmaydi — tizim ularni o'zi boshqaradi.

Uzoq kritik seksiyalar

Agar thread qulfni juda uzoq ushlab tursa (synchronized bloki ichida og'ir hisoblashlar, tarmoq so'rovlari yoki fayl operatsiyalarini bajarilsa), bu qulfni kutayotgan boshqa threadlar ochlik chekadi. Bu ayniqsa Androidda xavfli, bu yerda UI threaddagi uzoq operatsiyalar ANRga sabab bo'ladi va ularni fon threadlariga o'tkazish kritik seksiyalarni optimallashtirmasdan Starvation muammosini ishchi threadlarga o'tkazadi.

Kotlin kodida Starvation namunasi

Bir misolni ko'rib chiqaylik, unda bir thread adolatsiz rejalashtirish tufayli qulfni juda tez-tez egallab oladi. Starvation yuqori prioritetli threadning cheksiz sikl orqali namoyish etiladi, bu past prioritetli threadga umumiy resursga kirishga imkon bermaydi.

kotlin
class SharedResource {
    private val lock = Any()

    fun criticalSection(id: String) {
        synchronized(lock) {
            println("$id kirish oldi")
            Thread.sleep(10)  // ish simulyatsiyasi
        }
    }
}

fun main() {
    val resource = SharedResource()

    // Yuqori prioritetli thread — doimiy faol
    val highPriority = Thread {
        while (true) {
            resource.criticalSection("High")
        }
    }

    // Past prioritetli thread — hech qachon kirish ololmasligi mumkin
    val lowPriority = Thread {
        while (true) {
            resource.criticalSection("Low")
        }
    }

    highPriority.start()
    lowPriority.start()
    // "Low" hech qachon xabarni chiqarmasligi mumkin — Starvation!
}

Bu misolda highPriority threadi doimiy ravishda qulfni egallab oladi va uni faqat 10 msga qo'yib beradi. synchronizedning adolatsiz xususiyati tufayli JVM rejalashtiruvchisi yuqori ehtimollik bilan qulfni yana o'sha threadga beradi — past prioritetli thread ochlik chekadi. Yechim — fair flagi bilan ReentrantLock(true) dan foydalanish, bu kutish navbatida tartibni kafolatlaydi.

Fair lock bilan tuzatilgan versiya resursga kirishning adolatli taqsimlanishini ta'minlaydi.

kotlin
class FairSharedResource {
    private val fairLock = ReentrantLock(true)  // fair = true

    fun criticalSection(id: String) {
        fairLock.lock()
        try {
            println("$id kirish oldi (fair)")
            Thread.sleep(10)
        } finally {
            fairLock.unlock()
        }
    }
}

Starvation vs Deadlock vs Livelock

Uch klassik ko'p threadlilik muammosi — Starvation, Deadlock va Livelock — ko'pincha birlashtiriladi, lekin ularning mexanizmlari va bartaraf etish usullari turlicha. Starvation — thread tayyor, lekin resurs olmaydi. Deadlock — threadlar siklik kutish bilan bloklangan. Livelock — threadlar faol, lekin rivojlanmaydi.

ParametrStarvationDeadlockLivelock
Thread holatiRUNNABLEBLOCKEDRUNNABLE
RivojlanishYo'qYo'qYo'q (faol bo'lsa ham)
CPU iste'moliPastMinimalYuqori (100% gacha)
SababAdolatsiz rejalashtirishSiklik kutishMojaroga bir xil reaksiya
Asosiy yechimFair Lock, kritik seksiyalarni kamaytirishQulf ierarxiyasiQayta urinish limiti, eksponensial backoff

Starvation Deadlockdan kamroq kritik hisoblanadi, chunki u halokatli emas — yuk kamayganda ochlik chekayotgan thread baribir bajariladi. Biroq xotira va CPU cheklangan Android ilovalarining real foydalanish sharoitida Starvation daqiqalar davom etishi mumkin, qabul qilib bo'lmaydigan UX yaratadi.

Starvationni qanday aniqlash mumkin

Thread Dump qisqa intervallarda takroriy olish bilan — ochlikni aniqlashning asosiy usuli. Agar thread izchil RUNNABLE holatida bo'lsa, lekin uning chaqiruv steklari bir nechta dump davomida o'zgarmasa — bu Starvationning klassik belgisidir. Android Studio da buning uchun vaqt davomida threadlar holatini yozib oluvchi Android Profiler ishlatiladi.

Avtomatlashtirilgan aniqlash vazifalarning bajarilish vaqtini kuzatish orqali mumkin. Agar bashorat qilinadigan bajarilish vaqti (masalan, 50 ms) bo'lgan vazifa 5 soniya yoki undan ko'proq bajarilsa — Starvation ehtimoli yuqori. Mobil ilovalarda Firebase Performance Monitoring kritik seksiyalar uchun maxsus izlarni (custom traces) sozlash va chegara qiymatlari oshib ketganda bildirishnomalar olish imkonini beradi.

synchronized bloklari sababli Starvation diagnostikasi uchun Java Flight Recorder (JFR) (Androidda OpenJDK API orqali mavjud) yoki Async Profiler dan foydalaning. Bu vositalar qaysi monitorlar eng uzoq kutish vaqtiga ega ekanligini va qaysi threadlar har bir monitor uchun raqobatlashayotganini ko'rsatadi. JFR ma'lumotlari IntelliJ IDEA Ultimate bilan o'rnatilgan profiler orqali integratsiyalanadi.

Thread ochligining oldini olish usullari

Fair Lock (true flagi bilan ReentrantLock)

ReentrantLock(true) threadlar qulfni navbat tartibida (FIFO) olishini kafolatlaydi. synchronizeddan farqli o'laroq, fair lock qulfni qo'yib yuborgan threadning darhol uni qayta egallashiga yo'l qo'ymaydi. Bu Starvationni butunlay yo'q qiladi, garchi navbatni saqlash uchun qo'shimcha xarajatlar tufayli umumiy o'tkazish qobiliyatini 10-20% kamaytirsa ham.

Qulfsiz atomik strukturalar

Lock-free ma'lumot strukturalari (ConcurrentHashMap, AtomicReference, LongAdder) ta'rifi bo'yicha Starvationni istisno qiladi, chunki ularda bir thread tomonidan ushlab turiladigan qulflar yo'q. Barcha operatsiyalar protsessorning CAS ko'rsatmalaridan foydalanadi, bu cheklangan qadamlarda kamida bitta threadning rivojlanishini kafolatlaydi. Mobil ishlanma uchun vazifa navbatlari uchun ConcurrentLinkedQueue ni afzal ko'ring.

Qisqa kritik seksiyalar

Qulfni ushlab turish vaqtini minimallashtirish — Starvation xavfini kamaytirishning universal usuli. Og'ir operatsiyalarni (tarmoq, disk kiritish-chiqarish, murakkab hisoblashlar) synchronized blokidan tashqariga chiqaring. O'quvchilar kamdan-kam yozuvchilar tufayli ochlik chekmasligi uchun ReadWriteLock dan foydalaning. Kotlin Coroutines kutubxonasi OS threadini bloklamaydigan suspending mexanizmi bilan Mutexni taqdim etadi.

Shartli o'zgaruvchilar va signallar

Condition.await() va signal() ehtiyotkorlik bilan ishlatilishi kerak: Conditionda kutayotgan thread boshqa threadlar bilan birga uyg'onadi (spurious wakeup) va hammasi qulf uchun raqobatlashadi. Agar bir thread awaitdan so'ng darhol kutishga qaytsa, boshqalar esa qulfni egallashga ulgursa — ochlik chekayotgan thread cheksiz uyg'onib uxlab qolishi mumkin. Shartni har doim while siklida tekshiring, ifda emas, qayta tekshirishni kafolatlash uchun.

Tez-tez so'raladigan savollar

Starvation va Priority Inversion o'rtasidagi farq nima?

Priority Inversion — bu past prioritetli thread yuqori prioritetli thread uchun zarur bo'lgan qulfni ushlab turgan vaziyat. Natijada yuqori prioritetli thread past prioritetlini kutadi — prioritetlar teskari bo'ladi. Starvation kengroq muammo: thread prioritetdan qat'iy nazar, adolatsiz rejalashtirish yoki uzoq kritik seksiyalar tufayli resurs olmaydi.

Starvation bir threadli ilovada yuzaga kelishi mumkinmi?

Yo'q, Starvation — ko'p threadlilik muammosi. Bir threadli kodda resurslar uchun raqobat va thread rejalashtirishi mavjud emas. Biroq Starvation asinxron bir threadli kodda (masalan, JavaScript event loop) yuzaga kelishi mumkin, agar bir mikro vazifa setTimeout orqali nol kechikish bilan boshqalarning bajarilishini cheksiz kechiktirsa.

Java Memory Model Starvation bilan qanday bog'liq?

JMM (Java Memory Model) threadlar o'rtasida o'zgarishlarning ko'rinishi qoidalarini belgilaydi, lekin adolatli rejalashtirishni kafolatlamaydi. JMMga muvofiq synchronized sequential consistency — asosiy to'g'rilikni ta'minlaydi, lekin Starvationning oldini olmaydi. Adolat uchun JMM spetsifikatsiyasiga kirmagan qo'shimcha mexanizmlar talab qilinadi.

Android UI threadida Starvation nima?

UI thread (Main Thread) klassik ma'noda ochlik cheka olmaydi, chunki u eng yuqori prioritetga ega. Biroq Starvation UI thread ochlik chekayotgan fon threadining natijasini kutganda yuzaga keladi. Odatdagi ssenariy: AsyncTask yoki korutin ma'lumotlarni yuklaydi, lekin boshqa threadlar bilan raqobat tufayli ma'lumotlar bazasiga kirish ololmaydi va UI kutishda muzlaydi.

Kotlin Coroutinesda Starvationning oldini qanday olish mumkin?

Korutinlarda Starvationning oldini olish uchun Dispatchers.IO da limitedParallelism dan foydalaning, threadlarning tugashiga yo'l qo'ymaslik uchun. Sinxronizatsiya uchun kotlinx.coroutines.sync dan Mutex ni qo'llang — u korutinni to'xtatadi, threadni bloklamaydi, bu ochlik xavfini kamaytiradi. Korutinlarda runBlocking dan saqlaning, chunki u pool threadini egallab boshqa korutinlarning Starvationiga sabab bo'lishi mumkin.

Xulosa

  • Starvation — thread bajarishga tayyor bo'lsa-da, adolatsiz rejalashtirish tufayli resurs olmaydigan vaziyat
  • Deadlockdan farqli o'laroq, ochlikda thread RUNNABLE holatida va yuk kamayganda bajarilishi mumkin
  • Adolatsiz qulflar (synchronized) va prioritetlardan noto'g'ri foydalanish — Starvationning asosiy sabablari
  • Fair Lock (true flagi bilan ReentrantLock) FIFO kirish tartibini kafolatlaydi va ochlikni butunlay yo'q qiladi
  • Lock-free strukturalar (ConcurrentHashMap, AtomicReference) Starvationni arxitektura darajasida istisno qiladi
  • Thread Dump takroriy olish bilan va Java Flight Recorder — Starvation diagnostikasining samarali usullari
  • Qisqa kritik seksiyalar va ReadWriteLock yuqori yukli tizimlarda ochlik ehtimolini kamaytiradi

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing