Sobes.tech
Middle

Was ist ein Mutex, welche Arten von Mutexes gibt es und wie verwendet man sie?

sobes.tech KI

Antwort von AI

Der Mutex (vom englischen MUTual EXclusion) ist eine Synchronisationsprimitive, die verwendet wird, um exklusiven Zugriff auf eine gemeinsam genutzte Ressource zwischen konkurrierenden Goroutines zu gewährleisten. Er stellt sicher, dass zu jedem Zeitpunkt nur eine Goroutine den Mutex besitzen und auf die geschützten Daten zugreifen kann.

In Go stellt das Paket sync zwei Haupttypen von Mutexen bereit:

  • sync.Mutex: Standard-Mutex. Bietet die Methoden Lock() und Unlock(). Wenn der Mutex bereits gesperrt ist, blockiert der Aufruf von Lock() die aktuelle Goroutine, bis er freigegeben wird. Unlock() entsperrt den Mutex.

    var mu sync.Mutex
    var counter int
    
    func increment() {
        mu.Lock() // Sperrt den Zugriff auf counter
        counter++
        mu.Unlock() // Entsperrt den Zugriff
    }
    
  • sync.RWMutex: Mutex für Lesen/Schreiben. Erlaubt mehreren Goroutines gleichzeitig das Lesen der geschützten Ressource, aber nur einer Goroutine darf schreiben. Bietet die Methoden Lock(), Unlock() (für Schreiben), RLock() und RUnlock() (für Lesen).

    var rwMu sync.RWMutex
    var data []int
    
    func readData() {
        rwMu.RLock() // Sperrt für Lesen
        // Lesen von data
        fmt.Println(data)
        rwMu.RUnlock() // Entsperrt das Lesen
    }
    
    func writeData(val int) {
        rwMu.Lock() // Sperrt für Schreiben
        // Schreiben in data
        data = append(data, val)
        rwMu.Unlock() // Entsperrt das Schreiben
    }
    

Der Einsatz von Mutexen ist notwendig, um Race Conditions zu verhindern, wenn mehrere Goroutines versuchen, gleichzeitig dieselben Daten zu modifizieren, was zu unvorhersehbaren Ergebnissen führt.

Verwendungsregeln:

  1. Lock() aufrufen, bevor auf die geschützte Ressource zugegriffen wird.
  2. Unlock() aufrufen, nachdem der Zugriff beendet ist. Es wird empfohlen, defer mu.Unlock() zu verwenden, um die Freigabe auch im Falle eines Paniks zu garantieren.
  3. Nicht versuchen, einen bereits gesperrten Mutex aus derselben Goroutine zu sperren (kann zu Deadlocks führen).
  4. Nicht versuchen, einen nicht gesperrten Mutex zu entsperren.
  5. Bei Verwendung von RWMutex RLock/RUnlock für Leseoperationen und Lock/Unlock für Schreiboperationen verwenden.
  6. Mutexes dürfen nach der ersten Verwendung nicht kopiert werden. Übergeben Sie sie per Referenz oder Zeiger.

Beispiel für die Verwendung von defer:

func safeIncrement() {
    mu.Lock()
    defer mu.Unlock() // Garantiert die Freigabe
    counter++
}