Bosh sahifa Wiki Mutex

Mutex

Mutex — umumiy resursga bir vaqtning o‘zida faqat bitta thread yoki process kirishini ta’minlaydigan synchronization mexanizmi. Atama mutual exclusion iborasidan olingan.

Thread mutexni lock qiladi, critical sectionni bajaradi va unlock qiladi. Boshqa threadlar shu vaqt ichida kutadi.

Mutex shared data ustidagi race conditionni oldini olish uchun ishlatiladi.

Critical section

Birgalikda bajarilmasligi kerak bo‘lgan kod qismi critical section hisoblanadi.

Misol:

lock
balance = balance - amount
transaction yozish
unlock

Lock bo‘lmasa, ikki thread bir xil eski balance asosida noto‘g‘ri natija chiqarishi mumkin.

Lock va unlock

Mutex ikki asosiy holatga ega:

  • unlocked;
  • locked.

Thread lock qilishga urinadi.

Mutex bo‘sh bo‘lsa ownerga aylanadi. Band bo‘lsa kutadi.

Faqat owner unlock qilishi kerak.

Owner

Mutex qaysi thread tomonidan olinganini bilishi mumkin.

Boshqa thread unlock qilsa, xato yoki undefined behavior yuz beradi.

Bu binary semaphore’dan asosiy farqlardan biri.

Blocking mutex

Band mutexni kutayotgan thread sleeping holatiga o‘tadi.

Kernel uni uyg‘otmaguncha CPU ishlatmaydi.

Qisqa kutishda user-space fast path, uzoq kutishda kernel primitive ishlatilishi mumkin.

Linux futex bunga misol.

Spinlock

Spinlock band bo‘lsa, thread loopda tekshirishda davom etadi.

Juda qisqa critical section va kernel kontekstida foydali.

Uzoq kutishda CPUni bekorga band qiladi.

Sleep qilish mumkin bo‘lmagan interrupt kontekstida spinlock ishlatilishi mumkin.

Recursive mutex

Bir thread bir mutexni bir necha marta lock qila oladi.

Har lock uchun mos unlock kerak.

Bu recursive code’da qulay, lekin noto‘g‘ri dizaynni yashirishi va lock ownershipni murakkablashtirishi mumkin.

Read-write lock

Ko‘p reader bir vaqtda kirishi, writer esa eksklyuziv kirishi mumkin.

O‘qish juda ko‘p, yozish kam bo‘lgan state uchun foydali.

Reader yoki writer starvation siyosatga bog‘liq.

Bu oddiy mutexdan alohida synchronization turi.

Try lock

try_lock mutex bo‘sh bo‘lsa oladi, band bo‘lsa darhol qaytadi.

Qo‘llanishlar:

  • fallback;
  • deadlockdan qochish;
  • boshqa ish bajarish;
  • monitoring.

Try lock muvaffaqiyatsiz bo‘lishi xato emas, normal holat bo‘lishi mumkin.

Timed lock

Mutex ma’lum vaqtgacha kutiladi.

Timeout:

  • lock juda uzoq ushlanganini;
  • deadlock ehtimolini;
  • overloadni

aniqlashga yordam beradi.

Timeoutdan keyin critical operation bajarilmagan bo‘ladi.

Lock scope

Mutex faqat shared state uchun zarur bo‘lgan eng kichik kod qismini himoya qiladi.

Lock ichida:

bajarish contentionni oshiradi.

Biroq lockni juda erta qo‘yib yuborish data invariantni buzishi mumkin.

RAII

C++ kabi tillarda lock guard scope tugaganda mutexni avtomatik unlock qiladi.

Exception yoki erta return bo‘lsa ham lock bo‘shatiladi.

Boshqa tillarda with, defer yoki finally ishlatiladi.

Contention

Ko‘p thread bitta mutex uchun raqobat qilsa contention yuz beradi.

Belgilar:

Yechimlar:

Lock granularity

Coarse-grained lock

Katta state’ni bitta mutex himoya qiladi.

Sodda, lekin parallelizm kam.

Fine-grained lock

Turli qismlar alohida mutexga ega.

Parallelizm yuqori, ammo deadlock va boshqaruv murakkab.

Deadlock

Ikki thread locklarni teskari tartibda olsa deadlock bo‘lishi mumkin.

Thread A: lock M1, kut M2
Thread B: lock M2, kut M1

Barcha kod uchun global lock order belgilanadi.

Bir nechta mutexni atomik olish APIlari ham mavjud.

Priority inversion

Past priority thread mutexni ushlab turadi. Yuqori priority thread kutadi. O‘rta priority thread past priorityni CPUdan siqib chiqaradi.

Natijada yuqori priority bilvosita uzoq bloklanadi.

Priority inheritance mutex ownerining prioritysini vaqtincha oshiradi.

Robust mutex

Process-shared mutex owner process crash qilsa, lock doimiy band bo‘lib qolishi mumkin.

Robust mutex keyingi ownerga oldingi owner o‘lganini bildiradi.

Shared data inconsistent bo‘lishi mumkin va tiklash talab qilinadi.

Mutex va atomic

Oddiy counter uchun atomic operation mutexdan yengilroq bo‘lishi mumkin.

Murakkab invariant, bir nechta field yoki conditional update uchun mutex tushunarliroq.

Lock-free kod har doim tez yoki sodda emas.

Memory ordering

Mutex faqat navbatni emas, memory visibilityni ham ta’minlaydi.

Thread A lock ichida yozgan ma’lumotni unlockdan keyin mutexni olgan Thread B to‘g‘ri ko‘rishi kerak.

Compiler va CPU reordering synchronization qoidalari bilan boshqariladi.

Async mutex

Coroutine uchun oddiy blocking mutex event loopni to‘xtatishi mumkin.

Async mutex kutayotgan coroutine’ni suspend qiladi.

Lock ichida await qilish ehtiyotkorlik bilan bajariladi, chunki lock uzoq vaqt ushlanadi.

Diagnostika

Mutex muammosida:

  • owner;
  • waiters;
  • lock order;
  • hold time;
  • contention;
  • recursive call;
  • missing unlock;
  • priority;
  • thread dump;
  • profiler

tekshiriladi.

Threadlar ishlamay, bir-birini kutayotgan bo‘lsa deadlock graph tuziladi.

Lock convoy

Mutex bo‘shatilganda ko‘p thread navbat bilan uyg‘onib, ayni lock uchun raqobat qilsa lock convoy yuz beradi.

Bir sekin owner keyingi barcha thread latency’sini oshiradi.

Yechimlar:

  • critical sectionni qisqartirish;
  • lock sharding;
  • queue-based lock;
  • worker sonini cheklash;
  • ma’lumot oqimini qayta loyihalash.

False sharing

Turli mutex yoki counterlar bir CPU cache line’da joylashsa, mustaqil threadlar ham cache line’ni bir-biridan tortib olishi mumkin. Padding va data layout performance’ni yaxshilaydi.

Bog‘liq tushunchalar

Mutual exclusion, Critical section, Race condition, Semaphore, Spinlock, Read-write lock, Deadlock, Atomic operation, Futex