Avec l'amélioration des performances du matériel informatique, de plus en plus d'applications doivent gérer un grand nombre de tâches simultanées et asynchrones. Cela soulève la question : comment gérer ces tâches efficacement et garantir la qualité du code ? Le langage Go a la capacité inhérente de prendre en charge la programmation simultanée et asynchrone. Cet article présente la meilleure façon de mettre en œuvre la programmation simultanée et asynchrone à l'aide du langage Go.
1. Comprendre le modèle de programmation concurrente et asynchrone du langage Go
Le modèle de programmation concurrente et asynchrone du langage Go est implémenté sur la base de la goroutine et du canal. Goroutine est un thread léger qui peut exécuter plusieurs tâches simultanément dans un programme. Channel est un canal de communication entre goroutines, qui peut réaliser la transmission de données entre différentes goroutines.
Dans le langage Go, une nouvelle goroutine peut être démarrée en utilisant le mot-clé go. Comme indiqué ci-dessous :
go func() { // do something }()
Dans le code ci-dessus, func() représente le code de fonction à exécuter. Démarrer cette fonction avec le mot-clé go l'exécutera dans une nouvelle goroutine.
Dans le langage Go, le modèle CSP (Communicating Sequential Processes) est adopté, ce qui signifie que la concurrence et la collaboration s'effectuent via des canaux. Un canal a deux points de terminaison : l'envoi et la réception. La communication entre les goroutines peut être réalisée par des canaux d'envoi et de réception.
2. Comment créer et utiliser une chaîne
En langage Go, créez une chaîne via la fonction make. Ce qui suit consiste à créer un canal de type chaîne :
ch := make(chan string)
Utilisez le symbole < pour envoyer des données au canal :
ch <- "Hello world"
Utilisez le symbole < pour recevoir des données depuis le canal :
msg := <-ch
Remarque : S'il n'y a aucune donnée à recevoir, le programme bloquera l'opération de réception. De même, si le canal est plein, l'opération d'envoi sera bloquée.
Il existe également un mot-clé select dans le langage Go qui peut être utilisé pour sélectionner l'exécution de goroutine. Select peut contenir plusieurs cas, chaque cas est une opération de réception ou d'envoi d'un canal. Lorsque select est exécuté, il sélectionnera au hasard un cas disponible pour l'exécution. Si aucun cas n'est disponible, il sera bloqué.
Voici un exemple :
ch1 := make(chan int) ch2 := make(chan int) go func() { for i := 0; i < 10; i++ { ch1 <- i } }() go func() { for i := 0; i < 10; i++ { ch2 <- i } }() for i := 0; i < 20; i++ { select { case v := <-ch1: fmt.Println("ch1:", v) case v := <-ch2: fmt.Println("ch2:", v) } }
Dans l'exemple ci-dessus, nous avons créé deux goroutines, une pour envoyer des données à ch1 et l'autre à ch2. Utilisez ensuite l'instruction select dans la goroutine principale pour surveiller les données de ch1 et ch2. Lorsque les données sont disponibles, l'instruction case correspondante est exécutée.
3. Utilisez WaitGroup pour contrôler l'exécution de goroutine
Normalement, nous devons attendre la fin de l'exécution de toutes les goroutines avant d'effectuer d'autres opérations. Vous pouvez utiliser WaitGroup dans le package de synchronisation pour répondre à cette exigence. WaitGroup peut être utilisé pour attendre la fin d'un groupe de goroutines.
Ce qui suit est un exemple :
var wg sync.WaitGroup func main() { for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() // do something }() } wg.Wait() // All goroutines are done }
Dans l'exemple ci-dessus, nous avons créé 10 goroutines, et l'appel de la méthode Add dans WaitGroup indique que 10 goroutines seront exécutées. Utilisez ensuite defer stmt.Done() dans chaque goroutine pour indiquer à WaitGroup que la goroutine est terminée. Enfin, la méthode Wait est appelée dans la goroutine principale pour attendre que toutes les goroutines terminent leur exécution.
4. Utilisez sync.Mutex pour assurer la sécurité des données
En langage Go, si une variable sera accédée par plusieurs goroutines en même temps, alors vous devez utiliser un verrouiller pour assurer la sécurité des données. Les verrous peuvent être implémentés à l'aide de Mutex à partir du package de synchronisation.
Voici un exemple :
var mu sync.Mutex var count int func inc() { mu.Lock() defer mu.Unlock() count++ } func main() { for i := 0; i < 10; i++ { go inc() } time.Sleep(time.Second) fmt.Println("count:", count) }
Dans l'exemple ci-dessus, nous avons créé un objet .Mutex pour garantir que l'accès à count est thread-safe. Dans la fonction inc, nous acquérons d'abord le verrou puis le libérons en différé. Dans la fonction principale, nous démarrons 10 goroutines inc pour accéder au nombre.
5. Utilisez le package contextuel pour gérer les délais d'attente et les annulations
En langage Go, nous pouvons utiliser le package contextuel pour gérer les délais d'attente et les annulations afin d'éviter les fuites goroutines et le gaspillage de ressources . Le contexte peut définir des délais et annuler les signaux. Toutes les goroutines seront annulées lorsque le signal est déclenché.
Ce qui suit est un exemple :
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() ch := make(chan int) go func() { time.Sleep(time.Second * 5) ch <- 1 }() select { case <-ch: fmt.Println("received") case <-ctx.Done(): fmt.Println("timeout or cancelled") }
Dans l'exemple ci-dessus, nous utilisons la fonction context.WithTimeout pour créer un objet Context avec un délai d'attente de 3 secondes et démarrer un goroutine pour attendre 5 secondes. Dans l'instruction select, si la goroutine se termine dans les 3 secondes, imprimez « reçu », sinon imprimez « timeout ou annulé ».
6. Résumé
La programmation simultanée et asynchrone peut être facilement implémentée à l'aide du langage Go. En utilisant des goroutines et des canaux, nous pouvons créer des modèles de concurrence efficaces. Dans le même temps, l'utilisation de WaitGroup, Mutex et Context peut rendre notre programme plus sûr et plus robuste.
Bien sûr, si elles sont utilisées de manière inappropriée, une concurrence élevée et une programmation asynchrone peuvent également causer certains problèmes, tels que des conditions de concurrence, des blocages, la famine et d'autres problèmes. Par conséquent, lorsque vous utilisez une programmation concurrente et asynchrone, veillez à faire attention à la qualité et à l'exactitude du code.
Ce 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!