Sobes.tech
Middle

Mis on mutex, millised mutexi tüübid on olemas ja kuidas neid kasutada?

sobes.tech AI

Vastus AI-lt

Muteks (inglise keelest MUTual EXclusion) on sünkronsis primitives, mida kasutatakse jagatud ressursi erandliku juurdepääsu tagamiseks konkurentsivõimeliste gorutinide vahel. See tagab, et iga hetk võib ainult üks gorutin omada muteksi ja vastavalt sellele pääseda kaitstud andmetele.

Go paketis sync on kaks peamist muteksi tüüpi:

  • sync.Mutex: Standardne muteks. Pakub meetodeid Lock() ja Unlock(). Kui muteks on juba lukustatud, blokeerib Lock() jooksva gorutina kuni muteks vabastatakse. Unlock() vabastab muteksi.

    var mu sync.Mutex
    var counter int
    
    func increment() {
        mu.Lock() // Lukustab juurdepääsu counterile
        counter++
        mu.Unlock() // Vabastab juurdepääsu
    }
    
  • sync.RWMutex: Lugemis-/kirjutusmuteks. Lubab mitmel gorutinil samaaegselt lugeda kaitstud ressurssi, kuid ainult ühe kirjutada. Pakub meetodeid Lock(), Unlock() (kirjutamiseks), RLock() ja RUnlock() (lugemiseks).

    var rwMu sync.RWMutex
    var data []int
    
    func readData() {
        rwMu.RLock() // Lukustab lugemiseks
        // Loeb data
        fmt.Println(data)
        rwMu.RUnlock() // Vabastab lugemise
    }
    
    func writeData(val int) {
        rwMu.Lock() // Lukustab kirjutamiseks
        // Kirjutab data
        data = append(data, val)
        rwMu.Unlock() // Vabastab kirjutamise
    }
    

Muteksi kasutamine on vajalik, et vältida võistlusolukordi (race conditions), kui mitu gorutinit üritavad samaaegselt muuta samu andmeid, mis võib viia ettearvamatute tulemusteni.

Kasutusreeglid:

  1. Kutsuge Lock() enne kaitstud ressursile juurdepääsu.
  2. Kutsuge Unlock() pärast juurdepääsu lõppu. Soovitatav on kasutada defer mu.Unlock(), et tagada vabastamine isegi paanikase olukorra korral.
  3. Ära püüa lukustada juba lukustatud muteksi samast gorutinas (see võib põhjustada deadlocki).
  4. Ära püüa vabastada lukustamata muteksi.
  5. Kui kasutate RWMutex, kasutage RLock/RUnlock lugemiseks ja Lock/Unlock kirjutamiseks.
  6. Muteksi ei tohi pärast esimest kasutamist kopeerida. Neid edastatakse viite või näitaja kaudu.

Näide defer kasutamisest:

func safeIncrement() {
    mu.Lock()
    defer mu.Unlock() // Garantii vabastamisele
    counter++
}