Kas yra mutex, kokie tipai mutexų egzistuoja ir kaip juos naudoti?
sobes.tech AI
Atsakymas iš AI
Mūtas (iš anglų kalbos MUTual EXclusion) — tai sinchronizacijos primityvas, naudojamas užtikrinti išskirtinį prieigą prie bendro ištekliaus tarp konkuruojančių gorutinų. Jis garantuoja, kad bet kuriuo momentu tik viena gorutina gali turėti mūta ir atitinkamai naudotis saugomais duomenimis.
Go paketas sync siūlo du pagrindinius mūta tipus:
-
sync.Mutex: Standartinis mūtas. PateikiaLock()irUnlock()metodus. Jei mūtas jau užrakintas,Lock()kvietimas blokuoja dabartinę gorutina, kol jis nebus atlaisvintas.Unlock()atlaisvina mūta.var mu sync.Mutex var counter int func increment() { mu.Lock() // Užrakinti prieigą prie counter counter++ mu.Unlock() // Atlaisvinti prieigą } -
sync.RWMutex: Skaitymo/rašymo mūtas. Leidžia kelioms gorutinoms vienu metu skaityti saugomą išteklį, bet tik vienai rašyti. PateikiaLock(),Unlock()(rašymui),RLock()irRUnlock()(skaitymui) metodus.var rwMu sync.RWMutex var data []int func readData() { rwMu.RLock() // Užrakinti skaitymui // Skaityti data fmt.Println(data) rwMu.RUnlock() // Atlaisvinti skaitymą } func writeData(val int) { rwMu.Lock() // Užrakinti rašymui // Rašyti į data data = append(data, val) rwMu.Unlock() // Atlaisvinti rašymą }
Mūta naudojimas yra būtinas norint išvengti lenktynių sąlygų, kai keli gorutinai vienu metu bando modifikuoti tas pačias duomenų dalis, kas gali sukelti nenuspėjamus rezultatus.
Naudojimo taisyklės:
- Kviesti
Lock()prieš prieigą prie saugomo ištekliaus. - Kviesti
Unlock()po prieigos pabaigos. Rekomenduojama naudotidefer mu.Unlock()garantijai, kad išlaisvinimas įvyks net ir panikos atveju. - Negalima pakartotinai užrakinti jau užrakintą mūta iš tos pačios gorutinos (gali sukelti deadlock).
- Negalima atlaisvinti neužrakinto mūta.
- Naudojant
RWMutex, naudokiteRLock/RUnlockskaitymo operacijoms irLock/Unlockrašymo operacijoms. - Mūta neturėtų būti kopijuojami po pirmojo naudojimo. Juos perduokite nuoroda arba rodykle.
Pavyzdys naudojant defer:
func safeIncrement() {
mu.Lock()
defer mu.Unlock() // Garantuoja atlaisvinimą
counter++
}