Skip to content

MOOC NSI - fondamentaux.

Transcription de la vidéo

4.2.3.3 part1 : Programmer des threads en Python

[00:00:01]

Regardons maintenant comment on peut programmer des threads en Python. Commençons par un programme Python simple où nous allons créer un seul thread. Avant de regarder en détail comment on programme les threads en Python, rappelons que quand on lance un programme Python, nous lançons un processus et si nous ne créons pas plusieurs threads au sein du processus, nous avons un processus mono-thread. Cela veut dire que quand on lance le programme, nous avons un premier thread, un thread initial qui ici, va commencer par la fonction main. Nous l'appelons usuellement le thread main puisque dans beaucoup de langages, le premier thread doit commencer par l'exécution d'une fonction prédéfinie qui s'appelle main. Regardons maintenant comment on programme les threads dans Python. Pour cela, on utilise le module threading et la classe prédéfinie threading.Thread. Pour définir donc des threads spécifiques à utiliser dans notre programme, nous devons définir de nouvelles classes. Dans notre programme, nous avons une classe myThread qui hérite de la classe threading.Thread et qui va redéfinir les deux méthodes init et run. init est le constructeur, c'est-à-dire la méthode qui va être exécutée quand on crée un nouveau thread. Et run est la fonction qui va être utilisée quand on lance le thread. Cette fonction définit ce que le thread va exécuter. Donc, si nous commençons par le début du programme, nous avons le lancement du premier thread, le thread mainqui va exécuter les instructions qui sont données dans la fonction main.

[00:01:53]

Il va d'abord dire qu'il commence. Ensuite, il va créer un nouveau thread, en utilisant le constructeur, et ensuite il va lancer ce nouveau thread . Donc, à partir de là, nous allons avoir deux threads qui vont s'exécuter de manière indépendante et concurrente. Ce nouveau thread va exécuter les instructions qui sont données dans la fonction run. Ce qu'il faut faire attention, c'est de bien appeler start et non la fonction run, puisque c'est bien en appelant start, qu’il y a la création d'un flot d'exécution indépendant. Regardons maintenant deux traces d'exécution. Dans la première, nous avons d'abord l'affichage du thread main, ensuite, les deux affichages du thread créé et cela se termine par l'affichage du main. Dans la deuxième exécution, l'ordre est différent. Nous avons l'affichage du main , l'affichage du deuxième thread,de nouveau, l'affichage du main, et cela se termine par l'affichage du deuxième thread. Cela nous montre déjà que même dans ce programme simple, l'ordonnancement des threads peut être différent d'une exécution à l'autre. Pour voir encore mieux cet effet, regardons n programme un peu plus fourni. Ici, nous allons créer 4 threads en plus du thread main. Vous voyez deux versions du même programme. La différence est que dans le programme à gauche, ce que le thread initial va exécuter est concentré, regroupé, dans la fonction main. Ainsi, il est plus facile de voir que le thread initial va exécuter les instructions de la fonction main alors que les autres threads vont exécuter les instructions dans la fonction run.

[00:03:59]

Ce programme est plus lisible. Qu'est ce que nous allons faire ici? Le thread initial donc, va commencer par créer 4 threads. Ici, par contre, il va passer un argument supplémentaire au constructeur et cet argument est en fait une phrase pour que les différents threads nous saluent dans des langues différentes. Ensuite, après la création des threads, le thread main va lancer ces quatre threads. Donc après le lancement, nous allons avoir le thread main et quatre autres threads qui s'exécutent de manière indépendante et concurrente. La classe myThread a été enrichie. Nous avons changé le constructeur : nous avons rajouté un argument et dans le corps de ce constructeur, nous définissons un autre attribut pour la classe qui est un attribut phrase où nous allons garder la phrase que ce thread va devoir utiliser pour nous saluer. Le comportement du thread aussi a été un peu modifié nous avons toujours l'affichage pour marquer le début et la fin d'exécution, mais au milieu, nous avons une boucle qui va s'exécuter trois fois et qui va afficher le numéro d'itération et la salutation. Regardons deux traces d'exécution. À gauche, nous avons donc une exécution qui commence par l'affichage du thread main. Ensuite, nous avons le premier thread qui démarre, qui effectue ses 3 itérations, qui se termine. Ensuite, le 2ème thread il démarre, effectue ses 3 itérations et termine. On croirait que tous s'exécutent dans l'ordre.

[00:05:51]

Bon, le 3 et 4 sont un peu plus mélangés et au milieu, nous avons la terminaison du thread initial. Si nous faisons une deuxième exécution, nous avons un peu plus d' entrelacement. Donc effectivement, quand nous n'avons pas beaucoup de threads et quand nous avons un comportement qui est court, donc une exécution courte, nous pouvons avoir l'illusion que tout se passe toujours de la même manière et dans le même ordre. Ce qui n'est pas le cas. Pour voir ceci, dans ce programme en particulier, nous avons décidé donc de rallonger le comportement des threads en augmentant le nombre d'itérations. Donc ici, vous voyez une trace d'exécution où il est effectivement difficile de détecter un ordre quelconque. Donc, ce qui est important de retenir, c'est que donc, effectivement, l'ordonnancement des threads comme pour les processus, est non déterministe et donc change d'une exécution à l'autre. Ici, pour ce programme en particulier, nous voyons que si nous avons un ordre de lancement dans le programme qui est le main, 1,2, 3, 4, au niveau de l'affichage, ce que nous voyons, c'est main, 1, 2, 4, 3, et au niveau de la terminaison aussi, c'est quelque chose de différent : main, 2, 3, 4, 1.

Dans cette séquence, nous avons commencé à programmer des threads en Python. Nous avons vu que pour cela, nous utilisons une bibliothèque prédéfinie de Python. Nous avons compris qu'un programme Python a au moins un thread et les programmes multi-threadés sont non déterministes.