Sobes.tech
Middle

Mi az a mutex, milyen típusú mutexek léteznek és hogyan használjuk őket?

sobes.tech MI

Válasz az MI-től

A mutex (az angol MUTual EXclusion kifejezésből származik) egy szinkronizációs primitív, amelyet arra használnak, hogy kizárólagos hozzáférést biztosítsanak egy megosztott erőforráshoz a versengő gorutinok között. Garantálja, hogy bármikor csak egy gorutin birtokolhatja a mutexet, és hozzáférhet a védett adatokhoz.

Go-ban a sync csomag két fő mutex típust kínál:

  • sync.Mutex: Szabványos mutex. A Lock() és Unlock() metódusokat biztosítja. Ha a mutex már zárolva van, a Lock() hívás blokkolja az aktuális gorutint, amíg fel nem oldják. Az Unlock() feloldja a mutexet.

    var mu sync.Mutex
    var counter int
    
    func increment() {
        mu.Lock() // Zárolja a hozzáférést a counterhez
        counter++
        mu.Unlock() // Feloldja a hozzáférést
    }
    
  • sync.RWMutex: Olvasás/írás mutex. Lehetővé teszi, hogy több gorutin olvassa a védett erőforrást egyszerre, de csak egy írhat. A Lock(), Unlock() (írásra), RLock() és RUnlock() (olvasásra) metódusokat biztosít.

    var rwMu sync.RWMutex
    var data []int
    
    func readData() {
        rwMu.RLock() // Olvasásra zárol
        // Adatok olvasása
        fmt.Println(data)
        rwMu.RUnlock() // Feloldja az olvasást
    }
    
    func writeData(val int) {
        rwMu.Lock() // Írásra zárol
        // Adatok írása
        data = append(data, val)
        rwMu.Unlock() // Feloldja az írást
    }
    

A mutexek használata szükséges a versenyhelyzetek (race conditions) megelőzése érdekében, amikor több gorutin próbálja ugyanazokat az adatokat módosítani egyidejűleg, ami kiszámíthatatlan eredményekhez vezet.

Használati szabályok:

  1. Hívja meg a Lock()-ot a védett erőforráshoz való hozzáférés előtt.
  2. A hozzáférés befejezése után hívja meg az Unlock()-ot. Ajánlott a defer mu.Unlock() használata a zárolás garantálására még pánik esetén is.
  3. Ne próbálja meg ugyanabból a gorutinból zárolt mutexet zárolni (ez deadlock-hoz vezethet).
  4. Ne próbálja meg feloldani a zárolatlan mutexet.
  5. RWMutex használatakor RLock/RUnlock olvasási műveletekhez, Lock/Unlock írási műveletekhez használjon.
  6. A mutexeket nem szabad másolni az első használat után. Átadja őket referencia vagy pointer formájában.

Példa a defer használatára:

func safeIncrement() {
    mu.Lock()
    defer mu.Unlock() // Garantálja a zárolás feloldását
    counter++
}