Sobes.tech
Middle

Мьютекс деген эмне, кандай түрлөрү бар жана аларды кантип колдонуу керек?

sobes.tech AI

AIден жооп

Мьютекс (англ. MUTual EXclusion) — бөлүштүрүлгөн ресурска конкуренциялык горутиндер ортосунда эксклюзивдүү кирүүнү камсыздоо үчүн колдонулган синхрондоштуруу примитиви. Ал ар бир учурда бир гана горутина мьютекске ээ боло алат жана корголгон маалыматтарга кайрылышын камсыздайт.

Go'до sync пакети эки негизги мьютекс түрүн камсыздайт:

  • sync.Mutex: Стандарттык мьютекс. Lock() жана Unlock() методдорун камсыздайт. Эгер мьютекс алдын ала блоктолот болсо, Lock() учурдагы горутинаны токтотуп турат, анткени ал бошотулмайынча. Unlock() мьютексин бошотот.

    var mu sync.Mutex
    var counter int
    
    func increment() {
        mu.Lock() // counterге кирүүнү блоктоо
        counter++
        mu.Unlock() // бошотуу
    }
    
  • sync.RWMutex: окуу/жазуу үчүн мьютекс. Бул көптөгөн горутиндер бир убакта корголгон ресурсти окуй алат, бирок бир гана жазуучу болушу мүмкүн. Lock(), Unlock() (жазуу үчүн), RLock() жана RUnlock() (окуу үчүн) методдорун камсыздайт.

    var rwMu sync.RWMutex
    var data []int
    
    func readData() {
        rwMu.RLock() // окуу үчүн блоктоо
        // data окуу
        fmt.Println(data)
        rwMu.RUnlock() // бошотуу
    }
    
    func writeData(val int) {
        rwMu.Lock() // жазуу үчүн блоктоо
        // dataга жазуу
        data = append(data, val)
        rwMu.Unlock() // бошотуу
    }
    

Мьютекстерди колдонуу конкуренциялык шарттарды алдын алуу үчүн керек, мисалы, бир нече горутиндер бир убакта бирдей маалыматтарды өзгөртүүгө аракет кылганда, бул күтүлбөгөн натыйжаларга алып келиши мүмкүн.

Коомдоштуруучу эрежелер:

  1. Lock() функциясын корголгон ресурска кириш алдында чакырыңыз.
  2. Unlock() функциясын кириш аяктагандан кийин чакырыңыз. defer mu.Unlock() колдонуу сунушталат, ал бошотуу ишин кепилдейт, даже паника учурунда да.
  3. Бир эле горутинден мурда жабылган мьютекс кайра жаббоо керек (дедлокко алып келиши мүмкүн).
  4. Бош мьютексин ачууга аракет кылбоо керек.
  5. RWMutex колдонуп жатканда, RLock()/RUnlock() окуу үчүн, Lock()/Unlock() жазуу үчүн колдонулат.
  6. Мьютекстер биринчи колдонгондон кийин көчүрүлбөшү керек. Алар шилтеме же көрсөткүч аркылуу өткөрүлүшү керек.

defer колдонуу мисалы:

func safeIncrement() {
    mu.Lock()
    defer mu.Unlock() // Бошотуу кепилдиги
    counter++
}