Multithreading en Python avec exemple :Apprendre GIL en Python
Le langage de programmation Python vous permet d'utiliser le multitraitement ou le multithreading. Dans ce didacticiel, vous apprendrez à écrire des applications multithreads en Python.
Qu'est-ce qu'un fil ?
Un thread est une unité d'exécution en programmation concurrente. Le multithreading est une technique qui permet à un processeur d'exécuter plusieurs tâches d'un processus en même temps. Ces threads peuvent s'exécuter individuellement tout en partageant leurs ressources de processus.
Qu'est-ce qu'un processus ?
Un processus est essentiellement le programme en cours d'exécution. Lorsque vous démarrez une application sur votre ordinateur (comme un navigateur ou un éditeur de texte), le système d'exploitation crée un processus .
Qu'est-ce que le multithreading en Python ?
Multithreading en Python La programmation est une technique bien connue dans laquelle plusieurs threads d'un processus partagent leur espace de données avec le thread principal, ce qui rend le partage d'informations et la communication au sein des threads faciles et efficaces. Les threads sont plus légers que les processus. Plusieurs threads peuvent s'exécuter individuellement tout en partageant leurs ressources de processus. Le but du multithreading est d'exécuter plusieurs tâches et cellules de fonction en même temps.
Dans ce tutoriel, vous apprendrez,
- Qu'est-ce qu'un fil ?
- Qu'est-ce qu'un processus ?
- Qu'est-ce que le multithread ?
- Qu'est-ce que le multitraitement ?
- Multithreading Python contre multitraitement
- Pourquoi utiliser le multithread ?
- Multi-threading Python
- Les modules Thread et Threading
- Le module de fil
- Le module de filetage
- Interblocages et conditions de course
- Synchronisation des fils de discussion
- Qu'est-ce que GIL ?
- Pourquoi la GIL était-elle nécessaire ?
Qu'est-ce que le multitraitement ?
Le multitraitement vous permet d'exécuter simultanément plusieurs processus non liés. Ces processus ne partagent pas leurs ressources et communiquent via IPC.
Multithreading Python contre multitraitement
Pour comprendre les processus et les threads, considérez ce scénario :Un fichier .exe sur votre ordinateur est un programme. Lorsque vous l'ouvrez, le système d'exploitation le charge en mémoire et le processeur l'exécute. L'instance du programme en cours d'exécution est appelée le processus.
Chaque processus aura 2 composants fondamentaux :
- Le code
- Les données
Désormais, un processus peut contenir une ou plusieurs sous-parties appelées threads. Cela dépend de l'architecture du système d'exploitation. Vous pouvez considérer un thread comme une section du processus qui peut être exécutée séparément par le système d'exploitation.
En d'autres termes, il s'agit d'un flux d'instructions qui peut être exécuté indépendamment par le système d'exploitation. Les threads d'un même processus partagent les données de ce processus et sont conçus pour fonctionner ensemble afin de faciliter le parallélisme.
Pourquoi utiliser le multithread ?
Le multithreading vous permet de décomposer une application en plusieurs sous-tâches et d'exécuter ces tâches simultanément. Si vous utilisez correctement le multithreading, la vitesse, les performances et le rendu de votre application peuvent tous être améliorés.
Multi-threading Python
Python prend en charge les constructions pour le multitraitement ainsi que le multithreading. Dans ce didacticiel, vous vous concentrerez principalement sur la mise en œuvre du multithread applications avec python. Il existe deux modules principaux qui peuvent être utilisés pour gérer les threads en Python :
- Le fil et
- Le threading modules
Cependant, en python, il existe également ce qu'on appelle un verrou d'interpréteur global (GIL). Cela ne permet pas beaucoup de gain de performances et peut même réduire les performances de certaines applications multithread. Vous apprendrez tout à ce sujet dans les prochaines sections de ce didacticiel.
Les modules Thread et Threading
Les deux modules que vous découvrirez dans ce didacticiel sont le module de thread et le module de thread .
Cependant, le module de thread a longtemps été obsolète. À partir de Python 3, il a été désigné comme obsolète et n'est accessible qu'en tant que __thread pour la rétrocompatibilité.
Vous devez utiliser le threading de niveau supérieur module pour les applications que vous avez l'intention de déployer. Le module de fil de discussion n'a été couvert ici qu'à des fins éducatives.
Le module de fil
La syntaxe pour créer un nouveau thread à l'aide de ce module est la suivante :
thread.start_new_thread(function_name, arguments)
Très bien, maintenant vous avez couvert la théorie de base pour commencer à coder. Alors, ouvrez votre IDLE ou un bloc-notes et tapez ce qui suit :
import time import _thread def thread_test(name, wait): i = 0 while i <= 3: time.sleep(wait) print("Running %s\n" %name) i = i + 1 print("%s has finished execution" %name) if __name__ == "__main__": _thread.start_new_thread(thread_test, ("First Thread", 1)) _thread.start_new_thread(thread_test, ("Second Thread", 2)) _thread.start_new_thread(thread_test, ("Third Thread", 3))
Enregistrez le fichier et appuyez sur F5 pour exécuter le programme. Si tout a été fait correctement, voici la sortie que vous devriez voir :
Vous en apprendrez plus sur les conditions de course et comment les gérer dans les sections à venir
EXPLICATION DU CODE
- Ces instructions importent les modules time et thread qui sont utilisés pour gérer l'exécution et le retard des threads Python.
- Ici, vous avez défini une fonction appelée thread_test, qui sera appelé par le start_new_thread méthode. La fonction exécute une boucle while pendant quatre itérations et imprime le nom du thread qui l'a appelée. Une fois l'itération terminée, il imprime un message indiquant que le thread a terminé son exécution.
- Il s'agit de la section principale de votre programme. Ici, vous appelez simplement le start_new_thread méthode avec le thread_test fonction comme argument. Cela créera un nouveau thread pour la fonction que vous passez comme argument et commencera à l'exécuter. Notez que vous pouvez remplacer ceci (thread_ test) avec toute autre fonction que vous souhaitez exécuter en tant que thread.
Le module de filetage
Ce module est l'implémentation de haut niveau du threading en python et la norme de facto pour la gestion des applications multithread. Il fournit un large éventail de fonctionnalités par rapport au module de thread.
Voici une liste de quelques fonctions utiles définies dans ce module :
Nom de la fonction | Description |
---|---|
activeCount() | Renvoie le nombre de Thread objets encore vivants |
fil courant() | Renvoie l'objet courant de la classe Thread. |
énumérer() | Répertorie tous les objets Thread actifs. |
estDaemon() | Renvoie true si le thread est un démon. |
isAlive() | Renvoie vrai si le fil est toujours actif. |
Méthodes de classe de thread | |
start() | Démarre l'activité d'un thread. Il ne doit être appelé qu'une seule fois pour chaque thread car il générera une erreur d'exécution s'il est appelé plusieurs fois. |
exécuter() | Cette méthode indique l'activité d'un thread et peut être remplacée par une classe qui étend la classe Thread. |
join() | Il bloque l'exécution d'autre code jusqu'à ce que le thread sur lequel la méthode join() a été appelée soit terminé. |
Histoire :la classe Thread
Avant de commencer à coder des programmes multithreads à l'aide du module de threading, il est crucial de comprendre la classe Thread. La classe thread est la classe principale qui définit le modèle et les opérations d'un thread en python.
La façon la plus courante de créer une application python multithread est de déclarer une classe qui étend la classe Thread et remplace sa méthode run().
La classe Thread, en résumé, signifie une séquence de code qui s'exécute dans un thread séparé de contrôle.
Ainsi, lors de l'écriture d'une application multithread, vous ferez ce qui suit :
- définir une classe qui étend la classe Thread
- Remplacer le __init__ constructeur
- Remplacer le run() méthode
Une fois qu'un objet thread a été créé, le start() peut être utilisée pour commencer l'exécution de cette activité et la méthode join() peut être utilisée pour bloquer tout autre code jusqu'à la fin de l'activité en cours.
Maintenant, essayons d'utiliser le module de threading pour implémenter votre exemple précédent. Encore une fois, lancez votre IDLE et tapez ce qui suit :
import time import threading class threadtester (threading.Thread): def __init__(self, id, name, i): threading.Thread.__init__(self) self.id = id self.name = name self.i = i def run(self): thread_test(self.name, self.i, 5) print ("%s has finished execution " %self.name) def thread_test(name, wait, i): while i: time.sleep(wait) print ("Running %s \n" %name) i = i - 1 if __name__=="__main__": thread1 = threadtester(1, "First Thread", 1) thread2 = threadtester(2, "Second Thread", 2) thread3 = threadtester(3, "Third Thread", 3) thread1.start() thread2.start() thread3.start() thread1.join() thread2.join() thread3.join()
Ce sera le résultat lorsque vous exécuterez le code ci-dessus :
EXPLICATION DU CODE
- Cette partie est identique à notre exemple précédent. Ici, vous importez les modules time et thread qui sont utilisés pour gérer l'exécution et les retards des threads Python.
- Dans ce bit, vous créez une classe appelée threadtester, qui hérite ou étend le Thread classe du module de threading. C'est l'un des moyens les plus courants de créer des threads en python. Cependant, vous ne devez remplacer que le constructeur et le run() méthode dans votre application. Comme vous pouvez le voir dans l'exemple de code ci-dessus, le __init__ méthode (constructeur) a été remplacée. De même, vous avez également remplacé le run() méthode. Il contient le code que vous souhaitez exécuter dans un thread. Dans cet exemple, vous avez appelé la fonction thread_test().
- C'est la méthode thread_test() qui prend la valeur de i en tant qu'argument, le diminue de 1 à chaque itération et parcourt le reste du code jusqu'à ce que i devienne 0. À chaque itération, il imprime le nom du thread en cours d'exécution et dort pendant des secondes d'attente (ce qui est également pris comme argument ).
- thread1 =threadtester(1, "First Thread", 1) Ici, nous créons un thread et transmettons les trois paramètres que nous avons déclarés dans __init__. Le premier paramètre est l'identifiant du thread, le deuxième paramètre est le nom du thread et le troisième paramètre est le compteur, qui détermine combien de fois la boucle while doit s'exécuter.
- thread2.start() La méthode start est utilisée pour démarrer l'exécution d'un thread. En interne, la fonction start() appelle la méthode run() de votre classe.
- thread3.join() La méthode join() bloque l'exécution d'un autre code et attend que le thread sur lequel elle a été appelée se termine.
Comme vous le savez déjà, les threads qui sont dans le même processus ont accès à la mémoire et aux données de ce processus. Par conséquent, si plusieurs threads tentent de modifier ou d'accéder simultanément aux données, des erreurs peuvent s'infiltrer.
Dans la section suivante, vous verrez les différents types de complications qui peuvent apparaître lorsque les threads accèdent aux données et à la section critique sans vérifier les transactions d'accès existantes.
Interblocages et conditions de course
Avant d'en savoir plus sur les blocages et les conditions de concurrence, il sera utile de comprendre quelques définitions de base liées à la programmation simultanée :
- Section critiqueIl s'agit d'un fragment de code qui accède ou modifie des variables partagées et doit être exécuté comme une transaction atomique.
- Changement de contexteIl s'agit du processus suivi par un processeur pour stocker l'état d'un thread avant de passer d'une tâche à une autre afin qu'il puisse être repris à partir du même point ultérieurement.
Interblocages
Les blocages sont le problème le plus redouté auquel les développeurs sont confrontés lors de l'écriture d'applications concurrentes/multithreadées en python. La meilleure façon de comprendre les impasses est d'utiliser l'exemple de problème informatique classique connu sous le nom de problème des philosophes de la restauration.
L'énoncé du problème pour les philosophes de la restauration est le suivant :
Cinq philosophes sont assis sur une table ronde avec cinq assiettes de spaghetti (un type de pâtes) et cinq fourchettes, comme indiqué sur le schéma.
Python
- Fonction free() dans la bibliothèque C :comment l'utiliser ? Apprendre avec l'exemple
- Python String strip() Fonction avec EXAMPLE
- Python String count() avec des EXEMPLES
- Fonction Python round() avec EXEMPLES
- Fonction Python map() avec EXEMPLES
- Python Timeit() avec des exemples
- Compteur Python dans les collections avec exemple
- Python List count() avec des EXEMPLES
- Index de liste Python () avec exemple