Sobes.tech
Middle

Kas ir mutex, kādi mutex tipi pastāv un kā tos izmantot?

sobes.tech AI

Atbilde no AI

Mūts (no angļu valodas MUTual EXclusion) ir sinhronizācijas primitives, kas tiek izmantots, lai nodrošinātu izņēmuma piekļuvi koplietotajam resursam starp konkurējošām gorutinām. Tas garantē, ka jebkurā brīdī tikai viena gorutina var piederēt mūtam un attiecīgi piekļūt aizsargātajiem datiem.

Go paketē sync ir pieejami divi galvenie mūtu tipi:

  • sync.Mutex: Standarta mūts. Nodrošina Lock() un Unlock() metodes. Ja mūts jau ir bloķēts, Lock() izsaukums bloķē pašreizējo gorutinu līdz tas tiek atbrīvots. Unlock() atbrīvo mūtu.

    var mu sync.Mutex
    var counter int
    
    func increment() {
        mu.Lock() // Bloķēt piekļuvi counter
        counter++
        mu.Unlock() // Atbrīvot piekļuvi
    }
    
  • sync.RWMutex: Lasīšanas/ierakstīšanas mūts. Atļauj vairākām gorutinām vienlaikus lasīt aizsargāto resursu, bet tikai vienai rakstīt. Nodrošina Lock(), Unlock() (rakstīšanai), RLock() un RUnlock() (lasīšanai) metodes.

    var rwMu sync.RWMutex
    var data []int
    
    func readData() {
        rwMu.RLock() // Bloķēt lasīšanai
        // Lasīt datus
        fmt.Println(data)
        rwMu.RUnlock() // Atbrīvot lasīšanu
    }
    
    func writeData(val int) {
        rwMu.Lock() // Bloķēt rakstīšanai
        // Rakstīt datus
        data = append(data, val)
        rwMu.Unlock() // Atbrīvot rakstīšanu
    }
    

Mūtu izmantošana ir nepieciešama, lai novērstu sacensību stāvokļus, kad vairākas gorutinas vienlaikus mēģina modificēt tās pašas datu daļas, kas var novest pie neparedzamiem rezultātiem.

Noteikumi:

  1. Izsaukt Lock() pirms piekļuves aizsargātajam resursam.
  2. Izsaukt Unlock() pēc piekļuves beigām. Ieteicams izmantot defer mu.Unlock() garantijai, ka atbrīvošana notiks pat panikas gadījumā.
  3. Neatkārtoti aizslēgt jau aizslēgtu mūtu no tās pašas gorutinas (tas var novest pie deadlock).
  4. Neatbrīvot neaizslēgtu mūtu.
  5. Izmantojot RWMutex, lietojiet RLock/RUnlock lasīšanas operācijām un Lock/Unlock rakstīšanas operācijām.
  6. Mūti nedrīkst kopēt pēc pirmās lietošanas. Tos nodod ar atsauci vai rādītāju.

Piemērs ar defer:

func safeIncrement() {
    mu.Lock()
    defer mu.Unlock() // Garantē atbrīvošanu
    counter++
}