Qu'est-ce qu'un mutex, quels types de mutex existent et comment les utiliser?
sobes.tech IA
Réponse de l'IA
Un mutex (de l'anglais MUTual EXclusion) est une primitive de synchronisation utilisée pour garantir un accès exclusif à une ressource partagée entre goroutines concurrentes. Il garantit qu'à tout moment, seule une goroutine peut posséder le mutex et accéder aux données protégées.
Dans Go, le package sync fournit deux principaux types de mutex:
-
sync.Mutex: Mutex standard. Fournit les méthodesLock()etUnlock(). Si le mutex est déjà verrouillé, l'appel àLock()bloque la goroutine en cours jusqu'à ce qu'il soit libéré.Unlock()libère le mutex.var mu sync.Mutex var counter int func increment() { mu.Lock() // Verrouille l'accès à counter counter++ mu.Unlock() // Déverrouille l'accès } -
sync.RWMutex: Mutex pour lecture/écriture. Permet à plusieurs goroutines de lire simultanément la ressource protégée, mais une seule peut écrire. Fournit les méthodesLock(),Unlock()(pour l'écriture),RLock()etRUnlock()(pour la lecture).var rwMu sync.RWMutex var data []int func readData() { rwMu.RLock() // Verrouille pour la lecture // Lecture de data fmt.Println(data) rwMu.RUnlock() // Déverrouille la lecture } func writeData(val int) { rwMu.Lock() // Verrouille pour l'écriture // Écriture dans data data = append(data, val) rwMu.Unlock() // Déverrouille l'écriture }
L'utilisation de mutex est nécessaire pour prévenir les conditions de course (race conditions), lorsque plusieurs goroutines tentent de modifier les mêmes données simultanément, ce qui conduit à des résultats imprévisibles.
Règles d'utilisation:
- Appeler
Lock()avant d'accéder à la ressource protégée. - Appeler
Unlock()après avoir terminé l'accès. Il est recommandé d'utiliserdefer mu.Unlock()pour garantir la libération même en cas de panic. - Ne pas tenter de verrouiller un mutex déjà verrouillé depuis la même goroutine (cela peut entraîner un deadlock).
- Ne pas tenter de déverrouiller un mutex non verrouillé.
- Lors de l'utilisation de
RWMutex, utiliserRLock/RUnlockpour les opérations de lecture etLock/Unlockpour les opérations d'écriture. - Les mutex ne doivent pas être copiés après leur première utilisation. Transmettez-les par référence ou pointeur.
Exemple d'utilisation de defer:
func safeIncrement() {
mu.Lock()
defer mu.Unlock() // Garantit la libération
counter++
}