Mobil ilovalarda Mutex — bu nima, ishlash prinsipi va o'zaro eksklyuzivlikni qo'llash

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

Mutex (o'zaro eksklyuzivlik) — sinxronizatsiya primitividir, u faqat bitta thread har bir momentda kodning kritik qismini bajarishini kafolatlaydi. Microsoft Docs (Synchronization Objects, 2024) ga ko'ra, Mutex ning asosiy prinsipi egalikdir: Mutex ni egallagan thread uning egasiga aylanadi va uni faqat kritik qismdan chiqqanda bo'shatadi. Mutex — Race Condition ning oldini olish va ko'p threadli ilovalarda ma'lumotlar yaxlitligini ta'minlash uchun fundamental vositadir.

Asosiy ma'lumotlar

  • Mutex — resursga faqat bitta threadning bir vaqtda kirishini ta'minlaydigan o'zaro eksklyuzivlik mexanizmi
  • Egalik (ownership) — Mutex ning asosiy xususiyati: qulfni faqat uni egallagan thread bo'shata oladi
  • Semafordan farqli o'laroq ≥2 hisoblagich bilan, Mutex faqat 0 yoki 1 holatiga ega (ikkilik semafor)
  • Mutex bilan Deadlock bir nechta mutekslarni noto'g'ri egallash tartibida yuzaga keladi
  • Kotlin Coroutines da suspending Mutex OT threadini bloklamaydi, bu uni klassik ReentrantLock dan farqlaydi

Mutex nima?

Mutex (Mutual Exclusion — o'zaro eksklyuzivlik so'zining qisqartmasi) — ko'p threadli muhitda umumiy resursga kirishni boshqaradigan sinxronizatsiya obyektidir. Thread kritik qismga kirganda, Mutex ni egallaydi. Agar boshqa thread xuddi shu Mutex ni egallashga harakat qilsa, u birinchi thread qulfni bo'shatguncha kutish holatiga o'tadi.

Mutex arxitekturasi 1965 yilda Edsger Dijkstra tomonidan ishlab chiqilgan THE operatsion tizimiga borib taqaladi. Aynan Dijkstra semaforlar kontseptsiyasini kiritdi, ulardan keyin Mutex alohida holat sifatida ajralib chiqdi — egalik qo'llab-quvvatlangan ikkilik semafor. Zamonaviy OT lar (Linux, Windows, Android) Mutex ni yadro darajasida amalga oshiradi, bu turli jarayonlar o'rtasida ham sinxronizatsiyaning to'g'ri ishlashini ta'minlaydi.

Mutex ning asosiy xususiyati ownership (egalik) dir. Faqat muteksni egallagan thread uni bo'shata oladi. Bu Mutex ni ikkilik semafordan farqlaydi, unda har qanday thread signal (V-operatsiya) bajarishi mumkin. Egalik qulfning boshqa thread tomonidan tasodifiy bo'shatilishining oldini oladi, bu Mutex ni mobil ishlanmada odatiy sinxronizatsiya stsenariylari uchun xavfsizroq qiladi. Android Developer Docs (Processes and Threads, 2024) ga ko'ra, yuqori raqobatda Mutex ni synchronized o'rniga ishlatish unumdorlikni 30% ga oshirishi mumkin.

Mutex qanday ishlaydi

Holatlar va operatsiyalar

Mutex ikki holatdan birida bo'ladi: qulflangan (locked) — thread tomonidan egallangan; bo'sh (unlocked) — egallanmagan. Ikki asosiy operatsiya — lock() (egallash) va unlock() (bo'shatish). Agar Mutex allaqachon egallangan bo'lsa, lock() ni chaqirgan thread bo'shatilgunga qadar bloklanadi. JVM da bloklangan thread BLOCKED holatiga o'tadi va CPU sarflamaydi.

Kutayotgan threadlarni rejalashtirish

Mutex bo'shatilganda, sistem kutayotgan threadlardan qaysi biri qulfni olishini tanlaydi. Adolatsiz (non-fair) rejalashtirishda tanlov muteksni hozirgina bo'shatgan threadga tushishi mumkin — bu o'tkazish qobiliyatini oshiradi, lekin Starvation (ochlik) ga olib kelishi mumkin. Adolatli (fair) rejalashtiruvchi FIFO navbatidan foydalanadi: birinchi kutayotgan thread qulfni birinchi bo'lib oladi. ReentrantLock(true) aynan shu mexanizmni amalga oshiradi.

Rekursiv egallash (Reentrancy)

Java/Kotlin da Mutex ni amalga oshirishlarning aksariyati rekursiv (reentrant) egallashni qo'llab-quvvatlaydi. Agar thread allaqachon Mutex ga ega bo'lsa va yana lock() ni chaqirsa, operatsiya muvaffaqiyatli bo'ladi — Mutex o'zini bloklamaydi. Rekursiya hisoblagichi ortadi va thread unlock() ni lock() chaqirilgancha marta chaqirishi kerak. Bu rekursiv chaqiruvlar va ichma-ich kritik qismlar uchun muhimdir.

Kotlin kodida Mutex dan foydalanish misoli

Oddiy vazifani ko'rib chiqaylik — umumiy hisoblagichni ReentrantLock (Java/Kotlin da klassik Mutex) yordamida Race Condition dan himoya qilish. Mutex siz kod noto'g'ri natija berardi; Mutex bilan barcha 1000 thread hisoblagich qiymatini kafolatlangan holda oshiradi.

kotlin
import java.util.concurrent.locks.ReentrantLock

class MutexCounter {
    private val mutex = ReentrantLock()
    private var count = 0

    fun increment() {
        mutex.lock()
        try {
            count++  // kritik qism
        } finally {
            mutex.unlock()  // majburiy finally
        }
    }

    fun getCount(): Int {
        mutex.lock()
        try {
            return count
        } finally {
            mutex.unlock()
        }
    }
}

fun main() = runBlocking {
    val counter = MutexCounter()
    val jobs = List(1000) {
        launch(Dispatchers.Default) {
            counter.increment()
        }
    }
    jobs.forEach { it.join() }
    println(counter.getCount())  // Har doim 1000
}

Finally blokiga e'tibor bering — Mutex bilan ishlashda majburiy namunadir. Agar kritik qism ichida istisno yuz bersa, unlock() chaqirilmaydi va Mutex abadiy qulflangan qoladi — bu Deadlock ga olib keladi. Finally bloki qismning istalgan natijasida Mutex ning bo'shatilishini kafolatlaydi.

Kotlin da alternativ yondashuv — withLock kengaytma funksiyasidan foydalanish, u avtomatik ravishda lock/unlock ni finally bilan boshqaradi.

kotlin
fun increment() {
    mutex.withLock {  // lock + try/finally avtomatik
        count++
    }
}

fun getCount(): Int = mutex.withLock { count }

Mutex vs Semaphore vs Monitor

Ushbu uch sinxronizatsiya mexanizmi ko'pincha aralashtiriladi, garchi ular turli xususiyatlarga va qo'llanish sohalariga ega. Mutex — ikkilik, egalik bilan. Semaphore — ruxsatnomalar hisoblagichi, egaliksiz. Monitor — yuqori darajadagi mexanizm, Mutex ni shart o'zgaruvchilari (condition variables) bilan birlashtiradi. Farqlarni tushunish muayyan vazifa uchun to'g'ri vositani tanlashda muhim ahamiyatga ega.

ParametrMutexSemaphoreMonitor
TurIkkilik (0/1)Hisoblagichli (0..N)Ikkilik + shartlar
EgalikFaqat egasi unlock qila oladiHar qanday thread signal bera oladiFaqat egasi
RekursivlikOdatda ha (reentrant)Yo'qHa
Shartli kutishYo'q (Condition kerak)Yo'qIchki (wait/notify)
Java/Kotlin misoliReentrantLockSemaphore(permits)synchronized

Qachon Mutex tanlash: bitta resursni bir vaqtda kirishdan himoya qilish kerak — masalan, umumiy kolleksiya, fayl yoki hisoblagich. Qachon Semaphore tanlash — resurslar hovuziga bir vaqtda kirishlar sonini cheklash kerak, masalan 5 ta ulanish uchun ma'lumotlar bazasi hovuzi. Qachon Monitor tanlash — shartli kutish bilan sinxronizatsiya kerak, masalan wait/notify orqali ishlab chiqaruvchi-iste'molchi navbati. Zamonaviy Android ishlanmasida synchronized ko'pincha ReentrantLock yoki kotlinx.coroutines Mutex bilan almashtiriladi.

Mutex dan foydalanishdagi tipik xatolar

Finally da unutilgan unlock

Eng keng tarqalgan xato — unlock() chaqiruvi uchun finally blokining yo'qligi. Agar kritik qism ichida istisno yuz bersa, Mutex qulflangan qoladi va boshqa threadlar abadiy kutadi. Istisnolar mumkin emasligiga ishonchingiz komil bo'lsa ham — har doim try/finally yoki withLock dan foydalaning. Bu mobil ishlanmada ayniqsa muhim bo'lgan defensive printing prinsipidir, bu erda istisnolar xotira yetishmasligi yoki Configuration Changes tufayli yuz berishi mumkin.

Mutex ni turlicha egallash tartibi

Ilovada bir nechta Mutex ishlatilganda, ularni egallashning yagona tartibini o'rnatish muhimdir. Agar Thread A M1 → M2 ni, Thread B esa M2 → M1 ni egallasa, Deadlock yuzaga keladi. Katta loyihalarda (50 ming qatordan ko'p) qulflar tartibi arxitektura qarorida hujjatlashtiriladi va linterlar bilan tekshiriladi. IntelliJ IDEA dagi Lock Checker vositasi qulflarning izchil bo'lmagan egallash tartibini avtomatik aniqlaydi.

Juda uzoq kritik qism

Mutex ni 1-2 millisekunddan ortiq ushlab turish — noto'g'ri dizayn belgisidir. Kritik qism faqat minimal zarur operatsiyalarni o'z ichiga olishi kerak. Tarmoq so'rovlari, fayl kiritish-chiqarish va murakkab hisob-kitoblar bloklangan qismdan tashqarida bajarilishi kerak. Android da UI threadyadida qulfni uzoq ushlab turish kadrlarning tushib qolishiga (jank) va ANR ga olib keladi. Agar kritik qism asosan o'qish operatsiyalaridan iborat bo'lsa, ReadWriteLock dan foydalaning.

Kotlin Coroutines da Mutex

kotlinx.coroutines kutubxonasi klassik ReentrantLock dan tubdan farq qiladigan o'z Mutex amalga oshirishni taqdim etadi. Asosiy farq — suspending Mutex OT threadini bloklamaydi, balki korutinni qulf bo'shatilgunga qadar to'xtatadi. Bu shuni anglatadiki, joriy korutin Mutex ni kutayotganda thread boshqa korutinlarni bajarishi mumkin.

kotlin
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

class CoroutineCounter {
    private val mutex = Mutex()
    private var count = 0

    suspend fun increment() {
        mutex.withLock {  // suspending — threadni bloklamaydi
            count++
        }
    }

    suspend fun getCount(): Int = mutex.withLock { count }
}

kotlinx Mutex ning asosiy xususiyatlari: rekursiv emas (non-reentrant) — ReentrantLock dan farqli o'laroq, korutin o'zi egalik qilgan Mutex ni qayta egallay olmaydi. Agar bu kerak bo'lsa, Mutex o'rniga Semaphore(1) dan foydalaning. Bundan tashqari, kotlinx.coroutines dan Mutex bloklamaydi: suspend orqali to'xtatishdan foydalanadi, bu esa hovuz threadini bloklamaslikka imkon beradi.

Amalda, suspending Mutex korutin kodida klassik ReentrantLock dan ikki sababga ko'ra afzal: masshtablash — bir korutin Mutex ni kutadi, thread esa boshqa korutinlarga xizmat ko'rsatadi, bu tizimning o'tkazish qobiliyatini oshiradi; BlockedThread ning yo'qligi — bloklangan thread stekini saqlashga resurs sarflanmaydi. JetBrains (Kotlin Coroutines Guide, 2024) ga ko'ra, suspending Mutex dan foydalanish 100+ korutinda o'tkazish qobiliyatini 40% ga oshiradi.

Tez-tez beriladigan savollar

Mutex ikkilik semafordan nimasi bilan farqlanadi?

Egalik (ownership) — asosiy farq. Mutex qaysi thread uni egallaganini eslab qoladi va faqat shu thread uni bo'shata oladi. Ikkilik semafor (Semaphore(1)) ning egasi yo'q — har qanday thread release() ni bajarishi mumkin. Shuning uchun Mutex xavfsizroq: boshqa thread tasodifan birovning qulfini bo'shata olmaydi, semafor esa bo'shata oladi.

Qachon Mutex, qachon synchronized ishlatish kerak?

synchronized soddaroq va qisqaroq — uni vaqt cheklovi va adolat nazoratisiz oddiy kritik qismlar uchun ishlating. ReentrantLock ni vaqt cheklovi bilan TryLock, fair-rejalashtirish, Condition Variables yoki kutayotgan threadni to'xtatish (lockInterruptibly) kerak bo'lganda ishlating. Korutinlar uchun har doim kotlinx.coroutines.sync.Mutex dan foydalaning.

Spinlock nima va Mutex dan nimasi bilan farqlanadi?

Spinlock — thread uxlamaydigan, balki sikl (spin) ichida qulf holatini tekshiradigan blokirovkadir. Spinlock CPU sarflaydi, lekin kontekstni almashtirmaydi, bu uni qisqa kritik qismlar (10 ta ko'rsatmaga qadar) uchun foydali qiladi. Mutex thread ni BLOCKED holatiga o'tkazadi, bu kontekst almashinuvi sababli 10-50 mikrosekundga qimmatroq, lekin CPU sarflamaydi.

Mutex OT darajasida qanday tuzilgan?

Linux yadrosi darajasida Mutex futex (fast userspace mutex) orqali amalga oshirilgan. Thread avval qulfni userspace da atomik CAS (Compare-And-Swap) ko'rsatmasi orqali egallashga harakat qiladi. Mutex bo'sh bo'lsa — egallash syscall siz sodir bo'ladi. Band bo'lsa — thread futex(FUTEX_WAIT) syscall ni qiladi va uxlaydi. Bo'shatilganda futex(FUTEX_WAKE) syscall bir kutayotgan threadni uyg'otadi.

Mutex jarayonlararo bo'lishi mumkinmi?

Ha, jarayonlararo Mutex (inter-process mutex) mavjud. Windows da bu Named Mutex, Linux da — PTHREAD_PROCESS_SHARED atributi bilan pthread_mutexattr_setpshared. Android Bionic libc ham fayl deskriptorlari orqali jarayonlararo Mutex ni qo'llab-quvvatlaydi. Jarayonlararo Mutex lar turli ilovalar yoki jarayon va uning bola jarayonlari o'rtasida sinxronizatsiya uchun ishlatiladi.

Xulosa

  • Mutex — faqat bitta thread bir vaqtda kritik qismni bajarishini kafolatlaydigan o'zaro eksklyuzivlik primitividir
  • Egalik (ownership) Mutex ni ikkilik semafordan farqlaydi — faqat ega thread bo'shata oladi
  • ReentrantLock Java/Kotlin da — rekursiv egallash va TryLock qo'llab-quvvatlashi bilan klassik Mutex amalga oshirilishi
  • Finally bloki yoki withLock istisnolar paytida Deadlock ning oldini olish uchun majburiydir
  • kotlinx.coroutines dan suspending Mutex OT threadini bloklamaydi, korutinni to'xtatadi
  • Yagona egallash tartibi bir nechta Mutex — murakkab tizimlarda Deadlock dan qochishning yagona yo'li
  • Qisqa kritik qismlar (1-2 ms gacha) — Starvation siz ko'p threadli ilovalar unumdorligining kaliti

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