| 
             Dans l’exemple précédent nous avons vu comment gérer des compteurs d’état simples avec des opérations atomiques. Pour des états plus compliqués, on peut utiliser un _mutex_ pour accéder de manière sûre à des données à travers plusieurs goroutines.  | 
          |
	         
            package main
 | 
        |
	        
            import (
    "fmt"
    "math/rand"
    "runtime"
    "sync"
    "sync/atomic"
    "time"
)
 | 
        |
	        
            func main() {
 | 
        |
| 
             Pour notre exemple, l’état   | 
          
	        
                var state = make(map[int]int)
 | 
        
| 
             Ce   | 
          
	        
                var mutex = &sync.Mutex{}
 | 
        
| 
             Pour comparer l’approche avec des mutexes avec une autre que nous verrons plus tard,   | 
          
	        
                var ops int64 = 0
 | 
        
| 
             Ici on lance 100 goroutines pour exécuter des lectures répétées sur l’état.  | 
          
	        
                for r := 0; r < 100; r++ {
        go func() {
            total := 0
            for {
 | 
        
| 
             A chaque lecture, on sélectionne une
clé à laquelle on souhaite accéder,
on bloque le mutex avec   | 
          
	        
                            key := rand.Intn(5)
                mutex.Lock()
                total += state[key]
                mutex.Unlock()
                atomic.AddInt64(&ops, 1)
 | 
        
| 
             Pour nous assurer que cette goroutine
ne prend pas toutes les ressources, on
rend la main explicitement après
chaque opération avec
  | 
          
	        
                            runtime.Gosched()
            }
        }()
    }
 | 
        
| 
             On démarre également 10 goroutines pour simuler des écritures, de la même manière que pour les écritures.  | 
          
	        
                for w := 0; w < 10; w++ {
        go func() {
            for {
                key := rand.Intn(5)
                val := rand.Intn(100)
                mutex.Lock()
                state[key] = val
                mutex.Unlock()
                atomic.AddInt64(&ops, 1)
                runtime.Gosched()
            }
        }()
    }
 | 
        
| 
             On fait travailler les 10 goroutines sur les
  | 
          
	        
                time.Sleep(time.Second)
 | 
        
| 
             On rapporte le nombre total d’opérations réalisées.  | 
          
	        
                opsFinal := atomic.LoadInt64(&ops)
    fmt.Println("ops:", opsFinal)
 | 
        
| 
             Avec un verrou final sur le mutex de   | 
          
	        
                mutex.Lock()
    fmt.Println("state:", state)
    mutex.Unlock()
}
 | 
        
| 
             Lancer  le programme montre qu’on a exécuté environ
3,500,000 d’opérations sur   | 
          
	        
            $ go run mutexes.go
ops: 3598302
state: map[1:38 4:98 2:23 3:85 0:44]
 | 
        
| 
             Ensuite nous verrons comment implémenter la même gestion d’état avec uniquement des goroutines et des canaux.  | 
          
Exemple suivant: Goroutines à états.