Maison > développement back-end > Golang > Meilleures pratiques pour la programmation simultanée dans Golang : une exploration approfondie des méthodes d'optimisation de Goroutines

Meilleures pratiques pour la programmation simultanée dans Golang : une exploration approfondie des méthodes d'optimisation de Goroutines

PHPz
Libérer: 2023-07-17 11:06:04
original
1642 Les gens l'ont consulté

Meilleures pratiques pour la programmation simultanée dans Golang : exploration approfondie des méthodes d'optimisation des Goroutines

Introduction :
Avec l'application généralisée des processeurs multicœurs, la programmation simultanée est devenue une tendance de développement. En tant que langage convivial pour la programmation simultanée, Golang simplifie la programmation simultanée via des Goroutines (threads légers) et des canaux (mécanisme de communication). Cependant, pour profiter pleinement des avantages de Golang en matière de concurrence, vous devez avoir une compréhension approfondie des méthodes d'optimisation de Goroutines. Cet article explorera plusieurs techniques pour optimiser les performances des Goroutines, ainsi que des exemples de code correspondants.

1. Évitez la création et la destruction de trop de Goroutines
La création et la destruction de Goroutines coûtent cher, il faut donc éviter la création et la destruction inutiles de trop de Goroutines. Lors de la création de Goroutines, vous pouvez utiliser sync.WaitGroup pour attendre que toutes les Goroutines terminent leur travail. L'exemple de code est le suivant :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

func main() {

    var wg sync.WaitGroup

     

    for i := 0; i < 10; i++ {

        wg.Add(1)

        go func() {

            // Do some work

            wg.Done()

        }()

    }

     

    wg.Wait()

    fmt.Println("All Goroutines have finished.")

}

Copier après la connexion

2. Utilisation correcte de la communication entre les Goroutines
Golang fournit des canaux pour implémenter la communication entre les Goroutines, mais une mauvaise utilisation des canaux affectera les performances. Voici plusieurs suggestions pour optimiser la communication Goroutines :

  1. Évitez les canaux sans tampon : les canaux sans tampon entraîneront un blocage sur l'expéditeur et le destinataire. Il est recommandé d'utiliser des canaux en tampon ou d'utiliser des opérations d'envoi et de réception non bloquantes.
  2. Envoi et réception par lots : si vous devez envoyer ou recevoir fréquemment de petites quantités de données, il est recommandé d'utiliser des tranches ou des tampons pour les opérations par lots afin de réduire le nombre de communications.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

func main() {

    // 使用缓冲Channel,提高发送和接收的效率

    ch := make(chan int, 10)

     

    go func() {

        for i := 0; i < 10; i++ {

            ch <- i

        }

        close(ch)

    }()

     

    // 批量接收数据

    var data []int

    for num := range ch {

        data = append(data, num)

    }

     

    fmt.Println(data)

}

Copier après la connexion

3. Réduisez l'utilisation des verrous
Lors du partage de données entre plusieurs Goroutines, des verrous sont souvent nécessaires pour garantir la cohérence des données. Cependant, une utilisation excessive du verrouillage peut créer des goulots d’étranglement en termes de performances. Voici plusieurs façons de réduire l'utilisation des verrous :

  1. Utiliser des opérations atomiques : le package sync/atomic de Golang fournit des opérations atomiques pour éviter l'utilisation de verrous. Les opérations atomiques sont indépendantes et ne nécessitent pas de verrouillage de la mémoire partagée. L'exemple de code est le suivant :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

func main() {

    var total int32

     

    var wg sync.WaitGroup

    for i := 0; i < 100; i++ {

        wg.Add(1)

        go func() {

            atomic.AddInt32(&total, 1)

            wg.Done()

        }()

    }

     

    wg.Wait()

     

    fmt.Println("Total:", atomic.LoadInt32(&total))

}

Copier après la connexion
  1. Utiliser des verrous en lecture-écriture : si plusieurs Goroutines souhaitent effectuer des opérations de lecture, vous pouvez utiliser des verrous en lecture-écriture (sync.RWMutex) pour contrôler l'accès aux données. Les verrous de lecture peuvent être détenus par plusieurs Goroutines en même temps pour améliorer les performances de concurrence. L'exemple de code est le suivant :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

func main() {

    var (

        data    map[string]string

        dataRWM sync.RWMutex

    )

     

    // 向data中添加数据的过程

    go func() {

        dataRWM.Lock()

        defer dataRWM.Unlock()

         

        // Add data to data map

    }()

     

    // 获取data的长度

    go func() {

        dataRWM.RLock()

        defer dataRWM.RUnlock()

         

        length := len(data)

        fmt.Println("Length:", length)

    }()

     

    // 其他并发读操作

}

Copier après la connexion

4. Utilisez des primitives de synchronisation pour assurer la sécurité de la concurrence
Dans Golang, en plus des verrous et des canaux, d'autres primitives de synchronisation peuvent également être utilisées pour assurer la sécurité de la concurrence. Voici plusieurs primitives de synchronisation couramment utilisées :

  1. Once : assurez-vous qu'une certaine fonction n'est exécutée qu'une seule fois.

1

2

3

4

5

6

7

8

9

var once sync.Once

 

func setup() {

    // Do some setup work

}

 

func main() {

    once.Do(setup) // 只会执行一次

}

Copier après la connexion
  1. Cond : Les variables de condition peuvent implémenter la communication entre les Goroutines via des mécanismes d'attente et de notification.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

var (

    condition   sync.Cond

    isReady     bool

)

 

func init() {

    condition = *sync.NewCond(&sync.Mutex{})

}

 

func worker(id int) {

    condition.L.Lock()

    for !isReady {

        condition.Wait()

    }

    condition.L.Unlock()

     

    // Do some work

}

 

func main() {

    // 创建多个Goroutines

    for i := 0; i < 10; i++ {

        go worker(i)

    }

     

    // 执行某个触发条件的操作

    condition.L.Lock()

    isReady = true

    condition.Broadcast()

    condition.L.Unlock()

}

Copier après la connexion

Conclusion :
Cet article présente plusieurs méthodes pour optimiser les Goroutines, notamment en évitant la création et la destruction excessives de Goroutines, en utilisant rationnellement la communication entre les Goroutines, en réduisant l'utilisation de verrous et en utilisant des primitives de synchronisation pour garantir la sécurité de la concurrence. En appliquant correctement ces méthodes d'optimisation, les performances et l'efficacité de la programmation simultanée dans Golang peuvent être améliorées. Dans les applications pratiques, il est nécessaire de sélectionner une stratégie d’optimisation appropriée en fonction de la situation spécifique. Dans le même temps, vous devez également prêter attention à la relation entre les performances de concurrence et la lisibilité et la maintenabilité du code pour éviter une optimisation excessive.

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!

Étiquettes associées:
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