En programmation concurrente, le verrouillage est un mécanisme utilisé pour protéger les ressources partagées. Dans le langage Go, les verrous sont l'un des outils importants pour parvenir à la concurrence. Il garantit que lorsque plusieurs coroutines accèdent simultanément aux ressources partagées, une seule coroutine peut lire ou modifier ces ressources. Cet article présentera l'utilisation des verrous en langage Go pour aider les lecteurs à mieux comprendre la programmation simultanée.
Mutual Exclusion Lock est le mécanisme de verrouillage le plus couramment utilisé dans le langage Go. Cela garantit qu’une seule coroutine peut accéder à la section critique en même temps. En termes simples, un verrou mutex garantit qu'une seule coroutine peut y accéder en même temps en encapsulant la ressource partagée dans la section critique du verrouillage.
Utiliser les verrous mutex en langage Go est très simple. Nous pouvons utiliser le type Mutex dans le package de synchronisation pour créer un verrou mutex :
import "sync" var mutex = &sync.Mutex{}
Après cela, à l'emplacement où les ressources partagées doivent être protégées, nous pouvons utiliser le code suivant pour obtenir le verrou :
mutex.Lock() defer mutex.Unlock()
import ( "fmt" "sync" ) var count = 0 var mutex = &sync.Mutex{} func increment(wg *sync.WaitGroup) { mutex.Lock() defer mutex.Unlock() count++ wg.Done() } func main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go increment(&wg) } wg.Wait() fmt.Println("Count:", count) }
import "sync" var rwlock = &sync.RWMutex{}
import ( "fmt" "sync" ) var count = 0 var rwlock = &sync.RWMutex{} func increment(wg *sync.WaitGroup) { rwlock.Lock() defer rwlock.Unlock() count++ wg.Done() } func read(wg *sync.WaitGroup) { rwlock.RLock() defer rwlock.RUnlock() fmt.Println("Count:", count) wg.Done() } func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go increment(&wg) } wg.Wait() for i := 0; i < 5; i++ { wg.Add(1) go read(&wg) } wg.Wait() }
Dans cet exemple, nous avons ouvert simultanément 10 coroutines pour écrire des données sur le compteur et 5 coroutines pour lire les données du compteur. En utilisant des verrous en lecture-écriture, les programmes peuvent lire les ressources partagées de manière efficace tout en garantissant l'atomicité des opérations d'écriture.
Opérations atomiquesLe langage Go a plusieurs fonctions d'opération atomique intégrées, vous pouvez vous référer à la documentation officielle. Voici deux fonctions d’opération atomique couramment utilisées : atomic.Add et atomic.Load.
atomic.Add : effectue une opération d'addition atomique sur un entier.import ( "fmt" "sync/atomic" "time" ) var count int32 = 0 func increment(wg *sync.WaitGroup) { defer wg.Done() atomic.AddInt32(&count, 1) } func printCount() { fmt.Println("Count: ", atomic.LoadInt32(&count)) } func main() { var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go increment(&wg) } wg.Wait() printCount() time.Sleep(time.Second) for i := 0; i < 3; i++ { wg.Add(1) go increment(&wg) } wg.Wait() printCount() }
Dans cet exemple, nous utilisons la fonction atomic.Add pour effectuer des opérations d'addition atomique sur le compteur, et l'atomique .Load fonction atomiquement Lire la valeur du compteur manuellement. En utilisant des opérations atomiques, nous pouvons éviter la surcharge des verrous et obtenir une programmation simultanée plus efficace.
SummaryCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!