Un guide du programmeur pour aller Partie 3

Page 1 de 4

Go est réputé pour son approche simple de la concurrence – il fait partie du langage. Dans cette dernière partie de notre examen des points clés de Go, nous examinons en profondeur comment les goroutines et les canaux fonctionnent ensemble pour orchestrer la concurrence et le parallélisme.

Un guide des programmeurs sur les langues

languagecover

Contenu

  1. Octave
  2. Scratch 2 *modifié
  3. Node.js *modifié
  4. App Inventor 2 *modifié
  5. Prise en main de .NET IL
  6. NetLogo *modifié
  7. Petit basique *modifié
  8. Manuscrit *modifié
  9. Script Google Apps
  10. Python
  11. Google’s Go
    1. Guide du programmeur pour utiliser le code Visual Studio *modifié
    2. Guide du programmeur pour aller Partie 2 – Objets et interfaces *modifié
    3. Un guide du programmeur pour aller Partie 3 – Goroutines et concurrence *modifié
  12. Guide de F #
  13. Rubis
    1. Approche orientée objet
    2. Un langage fonctionnel

goicon1

Partie 3 Concurrence, goroutines et canaux

Go adopte une approche particulièrement propre de la programmation orientée objet mais l’une des raisons pour lesquelles les gens y sont attirés est qu’il offre une implémentation très simple et efficace de la concurrence. Alors que d’autres langues proposent des threads et des méthodes similaires mais plus légères de travail avec la concurrence, Go n’introduit pratiquement rien de nouveau – vous utilisez simplement des goroutines et des canaux de communication. Cependant, vous devez faire attention à ne pas mal comprendre ce que vous obtenez.

Le goroutine

Go propose une approche très simple et directe – le goroutine.

Un goroutine est juste une fonction invoquée à l’aide de l’instruction go. L’écriture

go function(parameters)

la fonction peut être une méthode et les paramètres sont évalués comme d’habitude.

La grande différence est que le programme appelant n’attend pas la fin de la fonction – c’est-à-dire qu’il s’agit d’un appel non bloquant et que la fonction démarre automatiquement, mais dans le même espace d’adressage que le code appelant.

Toutes les valeurs de retour qu’une goroutine pourrait avoir sont ignorées à la fin et si le code appelant est terminé, la goroutine se termine également.

Donc, si vous voulez démarrer une fonction en faisant quelque chose pendant que le programme principal passe à autre chose, vous avez besoin d’une goroutine.

Un fil?

Tout cela semble très simple, mais vous devez être très clair sur la façon dont tout cela fonctionne, alors regardons l’exemple le plus simple possible.

Commençons par une fonction qui imprime seulement 1000 valeurs

func count() { 
   for i := 0; i < 1000; i++ {
        fmt.Println(i)
    }
}

Notez que i est une variable locale.

Maintenant, si nous avons une fonction principale simple pour appeler la fonction, tout fonctionne comme vous pouvez vous y attendre – il n’y a rien de nouveau ici:

func main() {
    count()
}

Si vous exécutez cela, vous voyez les 1000 valeurs imprimées, puis l’habituel

“Processus de réussite terminé avec le code 0”

message indiquant que la fonction principale s’est terminée sans erreur.

Maintenant, convertissez l’appel en goroutine

func main() {
   go count()
}

Si vous essayez ceci, vous découvrirez que vous ne voyez rien du tout imprimé. La raison en est que le programme principal prend fin avant que le goroutine ait la chance de s’exécuter – alors ne partez pas.

Pour donner au goroutine le temps de s’exécuter, nous devons maintenir la fonction principale en cours d’exécution. La chose la plus évidente à faire est de mettre la fonction principale dans une boucle infinie:

func main() {

    runtime.GOMAXPROCS(1)

    go count()

    for {    }

}

ne vous inquiétez pas de l’appel à GOMAXPROCS, tout sera expliqué. Même si le goroutine principal continue de fonctionner, le goroutin de comptage ne s’exécute jamais.

Que se passe-t-il?

Go utilise un algorithme de planification assez simple qui a évolué au fil du temps.

Par défaut, le nombre de threads utilisés pour exécuter les goroutines est défini par le nombre de cœurs de la machine, mais vous pouvez le définir comme vous le souhaitez à l’aide de la fonction GOMAXPROCS. Dans ce cas, il a été défini sur un, ce qui signifie qu’il existe un seul thread pour exécuter tous les goroutines. Avec ces informations supplémentaires, vous devriez pouvoir voir ce qui se passe. Le goroutine principal n’abandonne jamais le seul thread disponible pour l’exécution et donc la routine count go ne s’exécute jamais.

Pour que le goroutine fonctionne réellement, la fonction principale doit bloquer et libérer le fil. C’est la fonction principale qui doit être suspendue en attendant que quelque chose se produise pour libérer le thread unique et que l’un des autres goroutines commence à s’exécuter.

Il y a un changement important dans le planificateur Go qui a été introduit dans Go 1.2. La planification jusqu’à 1.2 était coopérative dans le sens où un autre goroutine n’a eu la chance de s’exécuter que lorsque la routine Go en cours d’exécution a libéré le thread. Après Go 1.2, le planificateur est parfois appelé lorsque vous appelez une fonction. Cela signifie que toute boucle contenant un appel de fonction peut être interrompue et le thread passé à un autre goroutine.

Par défaut, le runtime Go alloue autant de threads que le processeur a de cœurs. Cela rend les choses un peu plus difficiles à comprendre lorsque vous commencez à utiliser des goroutines. Par exemple, si dans l’exemple précédent vous supprimez l’appel à GOMAXPROC et exécutez le programme sur un seul processeur cored, vous obtiendrez le même comportement. Cependant, si vous exécutez le programme sur une machine qui a plus d’un cœur, vous verrez le compte goroutine s’exécuter, imprimez 0 à 999, puis libérez son thread et le goroutine principal ne finira jamais de garder son thread occupé jusqu’à ce que vous arrêtiez le débogage.

C’est un principe de conception important que le comportement d’un programme ne devrait pas dépendre du nombre de threads ou de cœurs dont il dispose pour l’exécuter. Cela signifie que notre exemple n’est pas bon, mais il montre comment les choses fonctionnent.

Pour le moment, il est plus simple de limiter notre attention à un seul thread et donc GOMAXPROC (1) est au début de chacun des exemples suivants – c’est-à-dire qu’il n’y a qu’un seul thread impliqué dans l’exécution des goroutines et ce qui se passe ne dépend pas de quelle machine vous utilisez.

Source

A propos admin

Découvrez également

Destiny 2: Bungie annonce le retour de Trials of Osiris

Après la fin de la restauration de la Fondation Empyrean par la communauté Destiny, le …

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *