Čo je mutex, aké typy mutexov existujú a ako ich používať?
sobes.tech AI
Odpoveď od AI
Mutex (od ang. MUTual EXclusion) je primitiv za sinhronizaciju koji se koristi za obezbeđivanje isključivog pristupa deljenom resursu između konkurentnih gorutina. On garantuje da u bilo kojem trenutku samo jedna gorutina može posedovati mutex i, shodno tome, pristupati zaštićenim podacima.
U Go, paket sync pruža dve glavne vrste mutexa:
-
sync.Mutex: Standardni mutex. Pruža metodeLock()iUnlock(). Ako je mutex već zaključan, pozivLock()blokira trenutnu gorutinu dok se ne oslobodi.Unlock()otključava mutex.var mu sync.Mutex var counter int func increment() { mu.Lock() // Zaključavamo pristup prema counter counter++ mu.Unlock() // Otključavamo pristup } -
sync.RWMutex: Mutex za čitanje/zapis. Omogućava više gorutina da istovremeno čitaju zaštićeni resurs, ali samo jednu da piše. Pruža metodeLock(),Unlock()(za zapis),RLock()iRUnlock()(za čitanje).var rwMu sync.RWMutex var data []int func readData() { rwMu.RLock() // Zaključavamo za čitanje // Čitanje data fmt.Println(data) rwMu.RUnlock() // Otključavamo čitanje } func writeData(val int) { rwMu.Lock() // Zaključavamo za zapis // Zapis u data data = append(data, val) rwMu.Unlock() // Otključavamo zapis }
Korišćenje mutexa je neophodno za sprečavanje stanja trke (race conditions), kada više gorutina istovremeno pokušava da modifikuje iste podatke, što može dovesti do nepredvidivih rezultata.
Pravila korišćenja:
- Pozovi
Lock()pre pristupa zaštićenom resursu. - Pozovi
Unlock()nakon završetka pristupa. Preporučljivo je koristitidefer mu.Unlock()za garantovanje otključavanja čak i u slučaju panike. - Ne pokušavaj da zaključavaš već zaključan mutex iz iste gorutine (može dovesti do deadlock-a).
- Ne pokušavaj da otključavaš nezaključan mutex.
- Kada koristiš
RWMutex, koristiRLock/RUnlockza operacije čitanja iLock/Unlockza operacije zapisivanja. - Mutexi ne smeju da se kopiraju nakon prve upotrebe. Trebaju se prosleđivati po referenci ili pokazivaču.
Primer korišćenja defer:
func safeIncrement() {
mu.Lock()
defer mu.Unlock() // Garantuje otključavanje
counter++
}