Maison > développement back-end > Golang > Golang implémente la concurrence

Golang implémente la concurrence

WBOY
Libérer: 2023-05-16 09:44:37
original
1106 Les gens l'ont consulté

Avec les progrès continus de la technologie informatique, l'efficacité opérationnelle et les performances des programmes modernes sont devenues des problèmes de plus en plus importants. La programmation simultanée est un moyen important d’améliorer l’efficacité et les performances de l’exécution d’un programme. En tant que langage de programmation émergent, les mécanismes uniques de goroutine et de canal de Golang rendent la programmation simultanée plus simple et plus efficace.

Cet article présentera les concepts de base de la programmation simultanée Golang et utilisera quelques exemples pour montrer comment utiliser les goroutines et les canaux pour créer des programmes simultanés efficaces.

1. Qu'est-ce que goroutine

Goroutine est un thread léger en golang. La taille de chaque goroutine n'est que d'environ 2 Ko, occupant très peu de mémoire et de ressources. De plus, le planificateur de Golang allouera automatiquement les goroutines à différents threads physiques pour l'exécution, réalisant ainsi une exécution simultanée.

Vous pouvez démarrer une goroutine via le mot-clé go, par exemple :

package main

import (
    "fmt"
    "time"
)

func printNums() {
    for i := 0; i < 5; i++ {
        fmt.Println(i)
        time.Sleep(time.Millisecond * 500)
    }
}

func main() {
    // 启动一个goroutine
    go printNums()

    // 继续执行主goroutine
    for i := 0; i < 5; i++ {
        fmt.Println("Hello")
        time.Sleep(time.Millisecond * 500)
    }
}
Copier après la connexion

Exécutez le programme ci-dessus, vous pouvez voir que les deux goroutines génèrent alternativement des nombres et Hello, réalisant ainsi une exécution simultanée.

2. Qu'est-ce qu'un canal

Un canal en Golang est une structure de données utilisée pour la communication et la synchronisation entre les goroutines. Les canaux peuvent transférer des données entre plusieurs goroutines et réaliser un échange sécurisé de données grâce au mécanisme de synchronisation du canal. Il existe deux types de canaux : avec et sans tampon. Les opérations d'envoi et de réception sur les canaux sans tampon sont bloquées jusqu'à ce que les opérations de réception et d'envoi correspondantes se produisent. Les canaux tampons peuvent atténuer dans une certaine mesure le décalage horaire entre les opérations d’envoi et de réception.

Voici un exemple d'utilisation d'un canal tamponné :

package main

import (
    "fmt"
    "time"
)

func main() {
    // 创建一个大小为2的带缓冲通道
    ch := make(chan string, 2)

    // 启动两个goroutine
    go func() {
        ch <- "Hello"
        ch <- "World"
    }()
    go func() {
        time.Sleep(time.Second)
        fmt.Println(<-ch)
        fmt.Println(<-ch)
    }()

    // 等待goroutine执行完毕
    time.Sleep(time.Second * 2)
}
Copier après la connexion

Dans l'exemple ci-dessus, nous avons créé un canal tamponné de taille 2. Ensuite, deux goroutines sont démarrées, l'une envoie deux chaînes au canal et l'autre reçoit les deux chaînes du canal et imprime la sortie. En raison de l'existence du tampon, il existe un certain décalage horaire entre les opérations d'envoi et de réception, mais les données peuvent toujours être transférées et synchronisées via le canal.

En plus des canaux tamponnés, golang prend également en charge les canaux non tamponnés, qui peuvent garantir plus strictement la synchronisation entre les goroutines.

3. Comment utiliser goroutine et canal pour obtenir la concurrence

Grâce à l'introduction précédente, nous pouvons voir que goroutine et canal sont des outils de programmation simultanée très utiles dans Golang. Ci-dessous, nous présenterons quelques exemples de la façon de les utiliser pour implémenter la programmation simultanée.

1. Téléchargez plusieurs pages Web simultanément

Grâce à goroutine et au canal, nous pouvons facilement télécharger plusieurs pages Web simultanément. Par exemple :

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

// 下载网页的函数
func download(url string, ch chan<- string) {
    resp, err := http.Get(url)
    if err != nil {
        ch <- fmt.Sprintf("%s error: %v", url, err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        ch <- fmt.Sprintf("%s error: %v", url, err)
        return
    }
    ch <- fmt.Sprintf("%s=%d", url, len(body))
}

func main() {
    // 要下载的网页列表
    urls := []string{
        "https://www.baidu.com",
        "https://www.google.com",
        "https://www.github.com",
    }

    // 创建一个无缓冲通道
    ch := make(chan string)

    // 启动多个goroutine下载网页
    for _, url := range urls {
        go download(url, ch)
    }

    // 从通道中读取结果,并打印输出
    for range urls {
        fmt.Println(<-ch)
    }

    // 等待goroutine执行完毕
    time.Sleep(time.Second * 2)
}
Copier après la connexion

Dans l'exemple ci-dessus, nous avons défini une fonction de téléchargement pour télécharger le contenu de la page Web de l'URL spécifiée et renvoyer le résultat via le canal. Ensuite, nous avons démarré plusieurs goroutines via la boucle for, et chaque goroutine a appelé la fonction de téléchargement pour télécharger une page Web. Une fois le résultat du téléchargement renvoyé via le canal, il est lu et imprimé dans la goroutine principale. De cette façon, nous pouvons facilement télécharger plusieurs pages Web simultanément et améliorer l'efficacité opérationnelle et les performances du programme.

2. Traitez plusieurs tâches simultanément

En plus de télécharger des pages Web, nous pouvons également utiliser goroutine et Channel pour traiter plusieurs tâches simultanément. Par exemple :

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
    for i := range jobs {
        fmt.Printf("worker %d start job %d
", id, i)
        time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
        fmt.Printf("worker %d finish job %d
", id, i)
        results <- i * 2
    }
}

func main() {
    // 定义要处理的任务列表
    jobCount := 10
    jobs := make(chan int, jobCount)
    for i := 0; i < jobCount; i++ {
        jobs <- i
    }
    close(jobs)

    // 定义结果通道
    results := make(chan int, jobCount)

    // 启动多个goroutine处理任务
    workerCount := 3
    for i := 0; i < workerCount; i++ {
        go worker(i, jobs, results)
    }

    // 从结果通道中读取结果,并打印输出
    for j := 0; j < jobCount; j++ {
        fmt.Println(<-results)
    }

    // 等待goroutine执行完毕
    time.Sleep(time.Second * 2)
}
Copier après la connexion

Dans l'exemple ci-dessus, nous avons défini une fonction de travail pour simuler le traitement de la tâche spécifiée. Ensuite, nous avons démarré plusieurs goroutines via une boucle for, chaque goroutine lisait une tâche depuis le canal jobs et la traitait. Les résultats du traitement sont renvoyés via le canal des résultats. Enfin, tous les résultats sont lus à partir du canal de résultats dans la goroutine principale et imprimés. De cette façon, nous pouvons facilement traiter plusieurs tâches simultanément et améliorer l’efficacité et les performances d’exécution du programme.

4. Résumé

Cet article présente les concepts de base de la programmation simultanée Golang, y compris l'utilisation de goroutine et de canal. À travers de multiples exemples, nous montrons comment utiliser les goroutines et les canaux pour créer des programmes simultanés efficaces. Comparé à d'autres langages de programmation, le modèle de programmation simultanée de Golang est plus concis et efficace, ce qui améliore considérablement l'efficacité et les performances d'exécution du programme. Cependant, il convient de noter qu'écrire des programmes concurrents de haute qualité n'est pas facile. Cela nécessite une compréhension et une maîtrise approfondies des mécanismes et des principes de la programmation simultanée Golang.

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal